Changeset 26637 in vbox
- Timestamp:
- Feb 18, 2010 8:40:38 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 57845
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 7 added
- 1 edited
- 16 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r26634 r26637 39 39 VBOX_WITH_UPDATE_REQUEST := 1 40 40 41 # Build new VirtualBox FE/Qt4 GUI runtime core. 42 # Currently its not used, you can build it for developing purposes. 43 #VBOX_WITH_NEW_RUNTIME_CORE := 1 41 44 42 45 # … … 224 227 ./src/X11 \ 225 228 ./src/darwin 229 ifdef VBOX_WITH_NEW_RUNTIME_CORE 230 VBOX_GUI_INC_DIRS += \ 231 ./src/runtime \ 232 ./src/runtime/normal 233 endif 226 234 227 235 VirtualBox_INCS = \ … … 360 368 src/widgets/VBoxSpecialControls.h \ 361 369 src/widgets/VBoxWarningPane.h 370 ifdef VBOX_WITH_NEW_RUNTIME_CORE 371 VirtualBox_QT_MOCHDRS += \ 372 src/runtime/UIActionsPool.h \ 373 src/runtime/UIIndicatorsPool.h \ 374 src/runtime/UIMachine.h \ 375 src/runtime/UIMachineLogic.h \ 376 src/runtime/UIMachineView.h \ 377 src/runtime/normal/UIMachineLogicNormal.h \ 378 src/runtime/normal/UIMachineWindowNormal.h \ 379 src/runtime/normal/UIMachineViewNormal.h 380 endif 362 381 363 382 # Sources containing local definitions of classes that use the Q_OBJECT macro. … … 367 386 src/VBoxMediaManagerDlg.cpp \ 368 387 src/wizards/registration/UIRegistrationWzd.cpp 388 ifdef VBOX_WITH_NEW_RUNTIME_CORE 389 VirtualBox_QT_MOCSRCS += \ 390 src/runtime/UIActionsPool.cpp \ 391 src/runtime/UIIndicatorsPool.cpp \ 392 src/runtime/UIMachine.cpp \ 393 src/runtime/UIMachineLogic.cpp 394 endif 369 395 ifdef VBOX_WITH_XPCOM 370 396 VirtualBox_QT_MOCSRCS += \ … … 463 489 src/widgets/VBoxSpecialControls.cpp \ 464 490 src/widgets/VBoxWarningPane.cpp 491 ifdef VBOX_WITH_NEW_RUNTIME_CORE 492 VirtualBox_SOURCES += \ 493 src/runtime/UIActionsPool.cpp \ 494 src/runtime/UIIndicatorsPool.cpp \ 495 src/runtime/UIFrameBuffer.cpp \ 496 src/runtime/UIMachine.cpp \ 497 src/runtime/UIMachineLogic.cpp \ 498 src/runtime/UIMachineWindow.cpp \ 499 src/runtime/UIMachineView.cpp \ 500 src/runtime/normal/UIMachineLogicNormal.cpp \ 501 src/runtime/normal/UIMachineWindowNormal.cpp \ 502 src/runtime/normal/UIMachineViewNormal.cpp 503 endif 465 504 466 505 ifeq ($(filter-out freebsd linux netbsd openbsd solaris,$(KBUILD_TARGET)),) # X11 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxFrameBuffer class and subclasses implementation4 * UIFrameBuffer class and subclasses implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 24 24 # include "precomp.h" 25 25 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 26 #include "VBoxFrameBuffer.h" 27 28 #include "VBoxConsoleView.h" 26 /* Global includes */ 27 #include <QPainter> 28 /* Local includes */ 29 #include "UIMachineView.h" 30 #include "UIFrameBuffer.h" 29 31 #include "VBoxProblemReporter.h" 30 32 #include "VBoxGlobal.h" 31 32 /* Qt includes */33 #include <QPainter>34 33 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 35 36 //37 // VBoxFrameBuffer class38 /////////////////////////////////////////////////////////////////////////////39 40 /** @class VBoxFrameBuffer41 *42 * Base class for all frame buffer implementations.43 */44 34 45 35 #if defined (Q_OS_WIN32) 46 36 static CComModule _Module; 47 37 #else 48 NS_DECL_CLASSINFO ( VBoxFrameBuffer)49 NS_IMPL_THREADSAFE_ISUPPORTS1_CI ( VBoxFrameBuffer, IFramebuffer)50 #endif 51 52 VBoxFrameBuffer::VBoxFrameBuffer (VBoxConsoleView *aView)53 : m View (aView)54 , m Wdt (0), mHgt(0)38 NS_DECL_CLASSINFO (UIFrameBuffer) 39 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (UIFrameBuffer, IFramebuffer) 40 #endif 41 42 UIFrameBuffer::UIFrameBuffer(UIMachineView *pMachineView) 43 : m_pMachineView(pMachineView) 44 , m_width(0), m_height(0) 55 45 #if defined (Q_OS_WIN32) 56 , refcnt(0)57 #endif 58 { 59 AssertMsg (mView, ("VBoxConsoleView must not be null\n"));60 m WinId = (mView && mView->viewport()) ? (ULONG64) mView->viewport()->winId() : 0;61 int rc = RTCritSectInit(&m CritSect);46 , m_iRefCnt(0) 47 #endif 48 { 49 AssertMsg(m_pMachineView, ("UIMachineView must not be null\n")); 50 m_uWinId = (m_pMachineView && m_pMachineView->viewport()) ? (ULONG64)m_pMachineView->viewport()->winId() : 0; 51 int rc = RTCritSectInit(&m_critSect); 62 52 AssertRC(rc); 63 53 } 64 54 65 VBoxFrameBuffer::~VBoxFrameBuffer() 66 { 67 RTCritSectDelete(&mCritSect); 68 } 69 70 // IFramebuffer implementation methods. 71 // Just forwarders to relevant class methods. 72 73 STDMETHODIMP VBoxFrameBuffer::COMGETTER(Address) (BYTE **aAddress) 74 { 75 if (!aAddress) 76 return E_POINTER; 77 *aAddress = address(); 78 return S_OK; 79 } 80 81 STDMETHODIMP VBoxFrameBuffer::COMGETTER(Width) (ULONG *aWidth) 82 { 83 if (!aWidth) 84 return E_POINTER; 85 *aWidth = (ULONG) width(); 86 return S_OK; 87 } 88 89 STDMETHODIMP VBoxFrameBuffer::COMGETTER(Height) (ULONG *aHeight) 90 { 91 if (!aHeight) 92 return E_POINTER; 93 *aHeight = (ULONG) height(); 94 return S_OK; 95 } 96 97 STDMETHODIMP VBoxFrameBuffer::COMGETTER(BitsPerPixel) (ULONG *aBitsPerPixel) 98 { 99 if (!aBitsPerPixel) 100 return E_POINTER; 101 *aBitsPerPixel = bitsPerPixel(); 102 return S_OK; 103 } 104 105 STDMETHODIMP VBoxFrameBuffer::COMGETTER(BytesPerLine) (ULONG *aBytesPerLine) 106 { 107 if (!aBytesPerLine) 108 return E_POINTER; 109 *aBytesPerLine = bytesPerLine(); 110 return S_OK; 111 } 112 113 STDMETHODIMP VBoxFrameBuffer::COMGETTER(PixelFormat) ( 114 ULONG *aPixelFormat) 115 { 116 if (!aPixelFormat) 117 return E_POINTER; 118 *aPixelFormat = pixelFormat(); 119 return S_OK; 120 } 121 122 STDMETHODIMP VBoxFrameBuffer::COMGETTER(UsesGuestVRAM) ( 123 BOOL *aUsesGuestVRAM) 124 { 125 if (!aUsesGuestVRAM) 126 return E_POINTER; 127 *aUsesGuestVRAM = usesGuestVRAM(); 128 return S_OK; 129 } 130 131 STDMETHODIMP VBoxFrameBuffer::COMGETTER(HeightReduction) (ULONG *aHeightReduction) 132 { 133 if (!aHeightReduction) 134 return E_POINTER; 135 /* no reduction */ 136 *aHeightReduction = 0; 137 return S_OK; 138 } 139 140 STDMETHODIMP VBoxFrameBuffer::COMGETTER(Overlay) (IFramebufferOverlay **aOverlay) 141 { 142 if (!aOverlay) 55 UIFrameBuffer::~UIFrameBuffer() 56 { 57 RTCritSectDelete(&m_critSect); 58 } 59 60 STDMETHODIMP UIFrameBuffer::COMGETTER(Address) (BYTE **ppAddress) 61 { 62 if (!ppAddress) 63 return E_POINTER; 64 *ppAddress = address(); 65 return S_OK; 66 } 67 68 STDMETHODIMP UIFrameBuffer::COMGETTER(Width) (ULONG *puWidth) 69 { 70 if (!puWidth) 71 return E_POINTER; 72 *puWidth = (ULONG)width(); 73 return S_OK; 74 } 75 76 STDMETHODIMP UIFrameBuffer::COMGETTER(Height) (ULONG *puHeight) 77 { 78 if (!puHeight) 79 return E_POINTER; 80 *puHeight = (ULONG)height(); 81 return S_OK; 82 } 83 84 STDMETHODIMP UIFrameBuffer::COMGETTER(BitsPerPixel) (ULONG *puBitsPerPixel) 85 { 86 if (!puBitsPerPixel) 87 return E_POINTER; 88 *puBitsPerPixel = bitsPerPixel(); 89 return S_OK; 90 } 91 92 STDMETHODIMP UIFrameBuffer::COMGETTER(BytesPerLine) (ULONG *puBytesPerLine) 93 { 94 if (!puBytesPerLine) 95 return E_POINTER; 96 *puBytesPerLine = bytesPerLine(); 97 return S_OK; 98 } 99 100 STDMETHODIMP UIFrameBuffer::COMGETTER(PixelFormat) (ULONG *puPixelFormat) 101 { 102 if (!puPixelFormat) 103 return E_POINTER; 104 *puPixelFormat = pixelFormat(); 105 return S_OK; 106 } 107 108 STDMETHODIMP UIFrameBuffer::COMGETTER(UsesGuestVRAM) (BOOL *pbUsesGuestVRAM) 109 { 110 if (!pbUsesGuestVRAM) 111 return E_POINTER; 112 *pbUsesGuestVRAM = usesGuestVRAM(); 113 return S_OK; 114 } 115 116 STDMETHODIMP UIFrameBuffer::COMGETTER(HeightReduction) (ULONG *puHeightReduction) 117 { 118 if (!puHeightReduction) 119 return E_POINTER; 120 *puHeightReduction = 0; 121 return S_OK; 122 } 123 124 STDMETHODIMP UIFrameBuffer::COMGETTER(Overlay) (IFramebufferOverlay **ppOverlay) 125 { 126 if (!ppOverlay) 143 127 return E_POINTER; 144 128 /* not yet implemented */ 145 * aOverlay = 0;146 return S_OK; 147 } 148 149 STDMETHODIMP VBoxFrameBuffer::COMGETTER(WinId) (ULONG64 *winId)150 { 151 if (! winId)152 return E_POINTER; 153 * winId = mWinId;154 return S_OK; 155 } 156 157 STDMETHODIMP VBoxFrameBuffer::Lock()129 *ppOverlay = 0; 130 return S_OK; 131 } 132 133 STDMETHODIMP UIFrameBuffer::COMGETTER(WinId) (ULONG64 *puWinId) 134 { 135 if (!puWinId) 136 return E_POINTER; 137 *puWinId = m_uWinId; 138 return S_OK; 139 } 140 141 STDMETHODIMP UIFrameBuffer::Lock() 158 142 { 159 143 this->lock(); … … 161 145 } 162 146 163 STDMETHODIMP VBoxFrameBuffer::Unlock()147 STDMETHODIMP UIFrameBuffer::Unlock() 164 148 { 165 149 this->unlock(); … … 168 152 169 153 /** @note This method is called on EMT from under this object's lock */ 170 STDMETHODIMP VBoxFrameBuffer::RequestResize (ULONG aScreenId, ULONG aPixelFormat, 171 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine, 172 ULONG aWidth, ULONG aHeight, 173 BOOL *aFinished) 174 { 175 NOREF(aScreenId); 176 QApplication::postEvent (mView, 177 new VBoxResizeEvent (aPixelFormat, aVRAM, aBitsPerPixel, 178 aBytesPerLine, aWidth, aHeight)); 179 180 #ifdef DEBUG_sunlover 181 LogFlowFunc (("pixelFormat=%d, vram=%p, bpp=%d, bpl=%d, w=%d, h=%d\n", 182 aPixelFormat, aVRAM, aBitsPerPixel, aBytesPerLine, aWidth, aHeight)); 183 #endif /* DEBUG_sunlover */ 184 185 /* 186 * the resize has been postponed, return FALSE 187 * to cause the VM thread to sleep until IDisplay::ResizeFinished() 188 * is called from the VBoxResizeEvent event handler. 189 */ 190 191 *aFinished = FALSE; 154 STDMETHODIMP UIFrameBuffer::RequestResize(ULONG uScreenId, ULONG uPixelFormat, 155 BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine, 156 ULONG uWidth, ULONG uHeight, 157 BOOL *pbFinished) 158 { 159 NOREF(uScreenId); 160 QApplication::postEvent (m_pMachineView, 161 new UIResizeEvent(uPixelFormat, pVRAM, uBitsPerPixel, 162 uBytesPerLine, uWidth, uHeight)); 163 164 *pbFinished = FALSE; 192 165 return S_OK; 193 166 } … … 202 175 * @param supported pointer to result variable 203 176 */ 204 STDMETHODIMP VBoxFrameBuffer::VideoModeSupported (ULONG aWidth, ULONG aHeight, 205 ULONG aBPP, BOOL *aSupported) 206 { 207 NOREF(aBPP); 208 LogFlowThisFunc(("aWidth=%lu, aHeight=%lu, aBPP=%lu\n", 209 (unsigned long) aWidth, (unsigned long) aHeight, 210 (unsigned long) aBPP)); 211 if (!aSupported) 212 return E_POINTER; 213 *aSupported = TRUE; 214 QRect screen = mView->desktopGeometry(); 215 if ( (screen.width() != 0) 216 && (aWidth > (ULONG) screen.width()) 217 ) 218 *aSupported = FALSE; 219 if ( (screen.height() != 0) 220 && (aHeight > (ULONG) screen.height()) 221 ) 222 *aSupported = FALSE; 177 STDMETHODIMP UIFrameBuffer::VideoModeSupported(ULONG uWidth, ULONG uHeight, ULONG uBPP, BOOL *pbSupported) 178 { 179 NOREF(uBPP); 180 LogFlowThisFunc(("width=%lu, height=%lu, BPP=%lu\n", 181 (unsigned long)uWidth, (unsigned long)uHeight, (unsigned long)uBPP)); 182 if (!pbSupported) 183 return E_POINTER; 184 *pbSupported = TRUE; 185 QRect screen = m_pMachineView->desktopGeometry(); 186 if ((screen.width() != 0) && (uWidth > (ULONG)screen.width())) 187 *pbSupported = FALSE; 188 if ((screen.height() != 0) && (uHeight > (ULONG)screen.height())) 189 *pbSupported = FALSE; 223 190 LogFlowThisFunc(("screenW=%lu, screenH=%lu -> aSupported=%s\n", 224 screen.width(), screen.height(), *aSupported ? "TRUE" : "FALSE")); 225 return S_OK; 226 } 227 228 STDMETHODIMP VBoxFrameBuffer::GetVisibleRegion(BYTE *aRectangles, ULONG aCount, 229 ULONG *aCountCopied) 230 { 231 PRTRECT rects = (PRTRECT)aRectangles; 191 screen.width(), screen.height(), *pbSupported ? "TRUE" : "FALSE")); 192 return S_OK; 193 } 194 195 STDMETHODIMP UIFrameBuffer::GetVisibleRegion(BYTE *pRectangles, ULONG uCount, ULONG *puCountCopied) 196 { 197 PRTRECT rects = (PRTRECT)pRectangles; 232 198 233 199 if (!rects) 234 200 return E_POINTER; 235 201 236 /// @todo what and why? 237 238 NOREF(aCount); 239 NOREF(aCountCopied); 240 241 return S_OK; 242 } 243 244 STDMETHODIMP VBoxFrameBuffer::SetVisibleRegion (BYTE *aRectangles, ULONG aCount) 245 { 246 PRTRECT rects = (PRTRECT)aRectangles; 202 NOREF(uCount); 203 NOREF(puCountCopied); 204 205 return S_OK; 206 } 207 208 STDMETHODIMP UIFrameBuffer::SetVisibleRegion(BYTE *pRectangles, ULONG uCount) 209 { 210 PRTRECT rects = (PRTRECT)pRectangles; 247 211 248 212 if (!rects) … … 250 214 251 215 QRegion reg; 252 for (ULONG ind = 0; ind < aCount; ++ ind)216 for (ULONG ind = 0; ind < uCount; ++ ind) 253 217 { 254 218 QRect rect; 255 rect.setLeft 256 rect.setTop 219 rect.setLeft(rects->xLeft); 220 rect.setTop(rects->yTop); 257 221 /* QRect are inclusive */ 258 rect.setRight 259 rect.setBottom 222 rect.setRight(rects->xRight - 1); 223 rect.setBottom(rects->yBottom - 1); 260 224 reg += rect; 261 225 ++ rects; 262 226 } 263 QApplication::postEvent (mView, new VBoxSetRegionEvent(reg));264 265 return S_OK; 266 } 267 268 STDMETHODIMP VBoxFrameBuffer::ProcessVHWACommand(BYTE *pCommand)269 { 270 Q_UNUSED 227 QApplication::postEvent(m_pMachineView, new UISetRegionEvent(reg)); 228 229 return S_OK; 230 } 231 232 STDMETHODIMP UIFrameBuffer::ProcessVHWACommand(BYTE *pCommand) 233 { 234 Q_UNUSED(pCommand); 271 235 return E_NOTIMPL; 272 236 } 273 237 274 238 #ifdef VBOX_WITH_VIDEOHWACCEL 275 void VBoxFrameBuffer::doProcessVHWACommand(QEvent *pEvent)239 void UIFrameBuffer::doProcessVHWACommand(QEvent *pEvent) 276 240 { 277 241 Q_UNUSED(pEvent); … … 281 245 #endif 282 246 283 //284 // VBoxQImageFrameBuffer class285 /////////////////////////////////////////////////////////////////////////////286 287 247 #if defined (VBOX_GUI_USE_QIMAGE) 288 289 /** @class VBoxQImageFrameBuffer 248 /** @class UIFrameBufferQImage 290 249 * 291 * The VBoxQImageFrameBufferclass is a class that implements the IFrameBuffer250 * The UIFrameBufferQImage class is a class that implements the IFrameBuffer 292 251 * interface and uses QImage as the direct storage for VM display data. QImage 293 252 * is then converted to QPixmap and blitted to the console view widget. 294 253 */ 295 296 VBoxQImageFrameBuffer::VBoxQImageFrameBuffer (VBoxConsoleView *aView) : 297 VBoxFrameBuffer (aView) 254 UIFrameBufferQImage::UIFrameBufferQImage(UIMachineView *pMachineView) 255 : UIFrameBuffer(pMachineView) 298 256 { 299 257 /* Initialize the framebuffer the first time */ 300 resizeEvent (new VBoxResizeEvent (FramebufferPixelFormat_Opaque, 301 NULL, 0, 0, 640, 480)); 258 resizeEvent(new UIResizeEvent(FramebufferPixelFormat_Opaque, NULL, 0, 0, 640, 480)); 302 259 } 303 260 304 261 /** @note This method is called on EMT from under this object's lock */ 305 STDMETHODIMP VBoxQImageFrameBuffer::NotifyUpdate (ULONG aX, ULONG aY, 306 ULONG aW, ULONG aH) 262 STDMETHODIMP UIFrameBufferQImage::NotifyUpdate(ULONG uX, ULONG uY, ULONG uW, ULONG uH) 307 263 { 308 264 /* We're not on the GUI thread and update() isn't thread safe in … … 310 266 * on Linux (didn't check Qt 4.x there) and probably on other 311 267 * non-DOS platforms, so post the event instead. */ 312 QApplication::postEvent (mView, 313 new VBoxRepaintEvent (aX, aY, aW, aH)); 314 315 return S_OK; 316 } 317 318 void VBoxQImageFrameBuffer::paintEvent (QPaintEvent *pe) 319 { 320 const QRect &r = pe->rect().intersected (mView->viewport()->rect()); 321 322 /* Some outdated rectangle during processing VBoxResizeEvent */ 268 QApplication::postEvent(m_pMachineView, new UIRepaintEvent(uX, uY, uW, uH)); 269 270 return S_OK; 271 } 272 273 void UIFrameBufferQImage::paintEvent(QPaintEvent *pEvent) 274 { 275 const QRect &r = pEvent->rect().intersected(m_pMachineView->viewport()->rect()); 276 277 /* Some outdated rectangle during processing UIResizeEvent */ 323 278 if (r.isEmpty()) 324 279 return; 325 280 326 281 #if 0 327 LogFlowFunc (("%dx%d-%dx%d (img=%dx%d)\n", 328 r.x(), r.y(), r.width(), r.height(), 329 img.width(), img.height())); 330 #endif 331 332 QPainter painter (mView->viewport()); 333 334 if (r.width() < mWdt * 2 / 3) 282 LogFlowFunc (("%dx%d-%dx%d (img=%dx%d)\n", r.x(), r.y(), r.width(), r.height(), img.width(), img.height())); 283 #endif 284 285 QPainter painter(m_pMachineView->viewport()); 286 287 if (r.width() < m_width * 2 / 3) 335 288 { 336 289 /* This method is faster for narrow updates */ 337 m PM = QPixmap::fromImage (mImg.copy (r.x() + mView->contentsX(),338 r.y() + m View->contentsY(),290 m_PM = QPixmap::fromImage(m_img.copy(r.x() + m_pMachineView->contentsX(), 291 r.y() + m_pMachineView->contentsY(), 339 292 r.width(), r.height())); 340 painter.drawPixmap (r.x(), r.y(), mPM);293 painter.drawPixmap(r.x(), r.y(), m_PM); 341 294 } 342 295 else 343 296 { 344 297 /* This method is faster for wide updates */ 345 m PM = QPixmap::fromImage (QImage (mImg.scanLine (r.y() + mView->contentsY()),346 m Img.width(), r.height(), mImg.bytesPerLine(),298 m_PM = QPixmap::fromImage(QImage(m_img.scanLine (r.y() + m_pMachineView->contentsY()), 299 m_img.width(), r.height(), m_img.bytesPerLine(), 347 300 QImage::Format_RGB32)); 348 painter.drawPixmap (r.x(), r.y(), mPM, 349 r.x() + mView->contentsX(), 0, 0, 0); 350 } 351 } 352 353 void VBoxQImageFrameBuffer::resizeEvent (VBoxResizeEvent *re) 301 painter.drawPixmap(r.x(), r.y(), m_PM, r.x() + m_pMachineView->contentsX(), 0, 0, 0); 302 } 303 } 304 305 void UIFrameBufferQImage::resizeEvent(UIResizeEvent *pEvent) 354 306 { 355 307 #if 0 356 308 LogFlowFunc (("fmt=%d, vram=%p, bpp=%d, bpl=%d, width=%d, height=%d\n", 357 re->pixelFormat(), re->VRAM(),358 re->bitsPerPixel(), re->bytesPerLine(),359 re->width(), re->height()));360 #endif 361 362 m Wdt = re->width();363 m Hgt = re->height();364 365 bool remind = false;366 bool fallback = false;367 ulong bitsPerLine = re->bytesPerLine() * 8;309 pEvent->pixelFormat(), pEvent->VRAM(), 310 pEvent->bitsPerPixel(), pEvent->bytesPerLine(), 311 pEvent->width(), pEvent->height())); 312 #endif 313 314 m_width = pEvent->width(); 315 m_height = pEvent->height(); 316 317 bool bRemind = false; 318 bool bFallback = false; 319 ulong bitsPerLine = pEvent->bytesPerLine() * 8; 368 320 369 321 /* check if we support the pixel format and can use the guest VRAM directly */ 370 if ( re->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB)322 if (pEvent->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB) 371 323 { 372 324 QImage::Format format; 373 switch ( re->bitsPerPixel())325 switch (pEvent->bitsPerPixel()) 374 326 { 375 327 /* 32-, 8- and 1-bpp are the only depths supported by QImage */ … … 379 331 case 8: 380 332 format = QImage::Format_Indexed8; 381 remind = true;333 bRemind = true; 382 334 break; 383 335 case 1: 384 336 format = QImage::Format_Mono; 385 remind = true;337 bRemind = true; 386 338 break; 387 339 default: 388 340 format = QImage::Format_Invalid; /* set it to something so gcc keeps quiet. */ 389 remind = true;390 fallback = true;341 bRemind = true; 342 bFallback = true; 391 343 break; 392 344 } 393 345 394 if (! fallback)346 if (!bFallback) 395 347 { 396 348 /* QImage only supports 32-bit aligned scan lines... */ 397 Assert (( re->bytesPerLine() & 3) == 0);398 fallback = ((re->bytesPerLine() & 3) != 0);349 Assert ((pEvent->bytesPerLine() & 3) == 0); 350 bFallback = ((pEvent->bytesPerLine() & 3) != 0); 399 351 } 400 if (! fallback)352 if (!bFallback) 401 353 { 402 354 /* ...and the scan lines ought to be a whole number of pixels. */ 403 Assert ((bitsPerLine & ( re->bitsPerPixel() - 1)) == 0);404 fallback = ((bitsPerLine & (re->bitsPerPixel() - 1)) != 0);355 Assert ((bitsPerLine & (pEvent->bitsPerPixel() - 1)) == 0); 356 bFallback = ((bitsPerLine & (pEvent->bitsPerPixel() - 1)) != 0); 405 357 } 406 if (! fallback)407 { 408 ulong virtWdt = bitsPerLine / re->bitsPerPixel();409 m Img = QImage ((uchar *) re->VRAM(), virtWdt, mHgt, format);410 m PixelFormat = FramebufferPixelFormat_FOURCC_RGB;411 m UsesGuestVRAM = true;358 if (!bFallback) 359 { 360 ulong virtWdt = bitsPerLine / pEvent->bitsPerPixel(); 361 m_img = QImage ((uchar *) pEvent->VRAM(), virtWdt, m_height, format); 362 m_uPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 363 m_bUsesGuestVRAM = true; 412 364 } 413 365 } 414 366 else 415 367 { 416 fallback = true;417 } 418 419 if ( fallback)368 bFallback = true; 369 } 370 371 if (bFallback) 420 372 { 421 373 /* we don't support either the pixel format or the color depth, 422 * fallback to a self-provided 32bpp RGB buffer */423 m Img = QImage (mWdt, mHgt, QImage::Format_RGB32);424 m PixelFormat = FramebufferPixelFormat_FOURCC_RGB;425 m UsesGuestVRAM = false;426 } 427 428 if ( remind)374 * bFallback to a self-provided 32bpp RGB buffer */ 375 m_img = QImage (m_width, m_height, QImage::Format_RGB32); 376 m_uPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 377 m_bUsesGuestVRAM = false; 378 } 379 380 if (bRemind) 429 381 { 430 382 class RemindEvent : public VBoxAsyncEvent … … 439 391 } 440 392 }; 441 (new RemindEvent (re->bitsPerPixel()))->post(); 442 } 443 } 444 445 #endif 446 447 // 448 // VBoxQGLFrameBuffer class 449 ///////////////////////////////////////////////////////////////////////////// 450 393 (new RemindEvent (pEvent->bitsPerPixel()))->post(); 394 } 395 } 396 #endif 397 398 #if 0 451 399 #if defined (VBOX_GUI_USE_QGL) 452 453 /* The class is defined in VBoxFBQGL.cpp */ 454 455 #endif 456 457 // 458 // VBoxSDLFrameBuffer class 459 ///////////////////////////////////////////////////////////////////////////// 400 UIFrameBufferQGL::UIFrameBufferQGL(UIMachineView *pMachineView) 401 : UIFrameBuffer(pMachineView) 402 , m_cmdPipe(pMachineView) 403 { 404 #ifndef VBOXQGL_PROF_BASE 405 resizeEvent(new UIResizeEvent(FramebufferPixelFormat_Opaque, NULL, 0, 0, 640, 480)); 406 #else 407 resizeEvent(new UIResizeEvent(FramebufferPixelFormat_Opaque, NULL, 0, 0, VBOXQGL_PROF_WIDTH, VBOXQGL_PROF_HEIGHT)); 408 #endif 409 } 410 411 /** @note This method is called on EMT from under this object's lock */ 412 STDMETHODIMP UIFrameBufferQGL::NotifyUpdate (ULONG uX, ULONG uY, ULONG uW, ULONG uH) 413 { 414 #ifdef VBOXQGL_PROF_BASE 415 QApplication::postEvent(m_pMachineView, new UIRepaintEvent(uX, uY, uW, uH)); 416 #else 417 QRect r(uX, uY, uW, uH); 418 m_cmdPipe.postCmd(VBOXVHWA_PIPECMD_PAINT, &r, 0); 419 #endif 420 return S_OK; 421 } 422 423 #ifdef VBOXQGL_PROF_BASE 424 STDMETHODIMP UIFrameBufferQGL::RequestResize(ULONG uScreenId, ULONG uPixelFormat, 425 BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine, 426 ULONG uWidth, ULONG uHeight, 427 BOOL *pbFinished) 428 { 429 uWidth = VBOXQGL_PROF_WIDTH; 430 uHeight = VBOXQGL_PROF_HEIGHT; 431 UIFrameBuffer::RequestResize(uScreenId, uPixelFormat, aVRAM, uBitsPerPixel, uBytesPerLine, uWidth, uHeight, pbFinished); 432 433 for(;;) 434 { 435 ULONG uX = 0; 436 ULONG uY = 0; 437 ULONG uW = aWidth; 438 ULONG uH = aHeight; 439 NotifyUpdate(uX, uY, uW, uH); 440 RTThreadSleep(40); 441 } 442 return S_OK; 443 } 444 #endif 445 446 VBoxGLWidget* UIFrameBufferQGL::vboxWidget() 447 { 448 return (VBoxGLWidget*)m_pMachineView->viewport(); 449 } 450 451 void UIFrameBufferQGL::paintEvent(QPaintEvent *pEvent) 452 { 453 Q_UNUSED(pEvent); 454 VBoxGLWidget *pWidget = vboxWidget(); 455 pWidget->makeCurrent(); 456 457 QRect vp(m_pMachineView->contentsX(), m_pMachineView->contentsY(), pWidget->width(), pWidget->height()); 458 if (vp != pWidget->vboxViewport()) 459 { 460 pWidget->vboxDoUpdateViewport(vp); 461 } 462 463 pWidget->performDisplayAndSwap(true); 464 } 465 466 void UIFrameBufferQGL::resizeEvent(UIResizeEvent *pEvent) 467 { 468 m_width = pEvent->width(); 469 m_height = pEvent->height(); 470 471 vboxWidget()->vboxResizeEvent(pEvent); 472 } 473 474 /* processing the VHWA command, called from the GUI thread */ 475 void UIFrameBufferQGL::doProcessVHWACommand(QEvent *pEvent) 476 { 477 Q_UNUSED(pEvent); 478 vboxWidget()->vboxProcessVHWACommands(&m_cmdPipe); 479 } 480 481 #ifdef VBOX_WITH_VIDEOHWACCEL 482 STDMETHODIMP UIFrameBufferQGL::ProcessVHWACommand(BYTE *pCommand) 483 { 484 VBOXVHWACMD *pCmd = (VBOXVHWACMD*)pCommand; 485 /* indicate that we process and complete the command asynchronously */ 486 pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH; 487 /* post the command to the GUI thread for processing */ 488 m_cmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, 0); 489 return S_OK; 490 } 491 #endif 492 #endif 460 493 461 494 #if defined (VBOX_GUI_USE_SDL) 462 463 495 #include "VBoxX11Helper.h" 464 496 465 /** @class VBoxSDLFrameBuffer497 /** @class UIFrameBufferSDL 466 498 * 467 * The VBoxSDLFrameBufferclass is a class that implements the IFrameBuffer499 * The UIFrameBufferSDL class is a class that implements the IFrameBuffer 468 500 * interface and uses SDL to store and render VM display data. 469 501 */ 470 471 VBoxSDLFrameBuffer::VBoxSDLFrameBuffer (VBoxConsoleView *aView) : 472 VBoxFrameBuffer (aView) 473 { 474 mScreen = NULL; 475 mPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 476 mSurfVRAM = NULL; 502 UIFrameBufferSDL::UIFrameBufferSDL(UIMachineView *pMachineView) 503 : UIFrameBuffer(pMachineView) 504 { 505 m_pScreen = NULL; 506 m_uPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 507 m_pSurfVRAM = NULL; 477 508 478 509 X11ScreenSaverSettingsInit(); 479 resizeEvent (new VBoxResizeEvent (FramebufferPixelFormat_Opaque, 480 NULL, 0, 0, 640, 480)); 481 } 482 483 VBoxSDLFrameBuffer::~VBoxSDLFrameBuffer() 484 { 485 if (mSurfVRAM) 486 { 487 SDL_FreeSurface (mSurfVRAM); 488 mSurfVRAM = NULL; 510 resizeEvent(new UIResizeEvent(FramebufferPixelFormat_Opaque, NULL, 0, 0, 640, 480)); 511 } 512 513 UIFrameBufferSDL::~UIFrameBufferSDL() 514 { 515 if (m_pSurfVRAM) 516 { 517 SDL_FreeSurface(m_pSurfVRAM); 518 m_pSurfVRAM = NULL; 489 519 } 490 520 X11ScreenSaverSettingsSave(); 491 SDL_QuitSubSystem 521 SDL_QuitSubSystem(SDL_INIT_VIDEO); 492 522 X11ScreenSaverSettingsRestore(); 493 523 } 494 524 495 525 /** @note This method is called on EMT from under this object's lock */ 496 STDMETHODIMP VBoxSDLFrameBuffer::NotifyUpdate (ULONG aX, ULONG aY, 497 ULONG aW, ULONG aH) 526 STDMETHODIMP UIFrameBufferSDL::NotifyUpdate(ULONG uX, ULONG uY, ULONG uW, ULONG uH) 498 527 { 499 528 #if !defined (Q_WS_WIN) && !defined (Q_WS_PM) … … 501 530 on the Mac (4.2.x is), on Linux (didn't check Qt 4.x there) and 502 531 probably on other non-DOS platforms, so post the event instead. */ 503 QApplication::postEvent (mView, 504 new VBoxRepaintEvent (aX, aY, aW, aH)); 532 QApplication::postEvent (m_pMachineView, new UIRepaintEvent(uX, uY, uW, UH)); 505 533 #else 506 534 /* we're not on the GUI thread, so update() instead of repaint()! */ 507 mView->viewport()->update (aX - mView->contentsX(), 508 aY - mView->contentsY(), 509 aW, aH); 510 #endif 511 return S_OK; 512 } 513 514 void VBoxSDLFrameBuffer::paintEvent (QPaintEvent *pe) 515 { 516 if (mScreen) 517 { 518 #ifdef Q_WS_X11 519 /* make sure we don't conflict with Qt's drawing */ 520 //XSync(QPaintDevice::x11Display(), FALSE); 521 #endif 522 if (mScreen->pixels) 523 { 524 QRect r = pe->rect(); 525 526 if (mSurfVRAM) 535 m_pMachineView->viewport()->update(uX - m_pMachineView->contentsX(), uY - m_pMachineView->contentsY(), uW, uH); 536 #endif 537 return S_OK; 538 } 539 540 void UIFrameBufferSDL::paintEvent(QPaintEvent *pEvent) 541 { 542 if (m_pScreen) 543 { 544 if (m_pScreen->pixels) 545 { 546 QRect r = pEvent->rect(); 547 548 if (m_pSurfVRAM) 527 549 { 528 SDL_Rect rect = { (Sint16) r.x(), (Sint16) r.y(), 529 (Sint16) r.width(), (Sint16) r.height() }; 530 SDL_BlitSurface (mSurfVRAM, &rect, mScreen, &rect); 531 /** @todo may be: if ((mScreen->flags & SDL_HWSURFACE) == 0) */ 532 SDL_UpdateRect (mScreen, r.x(), r.y(), r.width(), r.height()); 550 SDL_Rect rect = { (Sint16)r.x(), (Sint16)r.y(), (Sint16)r.width(), (Sint16)r.height() }; 551 SDL_BlitSurface(m_pSurfVRAM, &rect, m_pScreen, &rect); 552 /** @todo may be: if ((m_pScreen->flags & SDL_HWSURFACE) == 0) */ 553 SDL_UpdateRect(m_pScreen, r.x(), r.y(), r.width(), r.height()); 533 554 } 534 555 else 535 556 { 536 SDL_UpdateRect (mScreen, r.x(), r.y(), r.width(), r.height());557 SDL_UpdateRect(m_pScreen, r.x(), r.y(), r.width(), r.height()); 537 558 } 538 559 } … … 540 561 } 541 562 542 void VBoxSDLFrameBuffer::resizeEvent (VBoxResizeEvent *re)563 void UIFrameBufferSDL::resizeEvent(UIResizeEvent *pEvent) 543 564 { 544 565 /* Check whether the guest resolution has not been changed. */ 545 bool fSameResolutionRequested = ( width() == re->width() 546 && height() == re->height() 547 ); 566 bool fSameResolutionRequested = (width() == pEvent->width() && height() == pEvent->height()); 548 567 549 568 /* Check if the guest VRAM can be used as the source bitmap. */ 550 bool fallback = false;569 bool bFallback = false; 551 570 552 571 Uint32 Rmask = 0; … … 554 573 Uint32 Bmask = 0; 555 574 556 if ( re->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB)557 { 558 switch ( re->bitsPerPixel())575 if (pEvent->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB) 576 { 577 switch (pEvent->bitsPerPixel()) 559 578 { 560 579 case 32: … … 575 594 default: 576 595 /* Unsupported format leads to the indirect buffer */ 577 fallback = true;596 bFallback = true; 578 597 break; 579 598 } … … 582 601 { 583 602 /* Unsupported format leads to the indirect buffer */ 584 fallback = true;585 } 586 587 m Wdt = re->width();588 m Hgt = re->height();603 bFallback = true; 604 } 605 606 m_width = pEvent->width(); 607 m_height = pEvent->height(); 589 608 590 609 /* Recreate the source surface. */ 591 if (m SurfVRAM)592 { 593 SDL_FreeSurface(m SurfVRAM);594 m SurfVRAM = NULL;595 } 596 597 if (! fallback)610 if (m_pSurfVRAM) 611 { 612 SDL_FreeSurface(m_pSurfVRAM); 613 m_pSurfVRAM = NULL; 614 } 615 616 if (!bFallback) 598 617 { 599 618 /* It is OK to create the source surface from the guest VRAM. */ 600 m SurfVRAM = SDL_CreateRGBSurfaceFrom(re->VRAM(), re->width(), re->height(),601 re->bitsPerPixel(),602 re->bytesPerLine(),603 Rmask, Gmask, Bmask, 0);604 LogFlowFunc (("Created VRAM surface %p\n", mSurfVRAM));605 if (m SurfVRAM == NULL)606 { 607 fallback = true;619 m_pSurfVRAM = SDL_CreateRGBSurfaceFrom(pEvent->VRAM(), pEvent->width(), pEvent->height(), 620 pEvent->bitsPerPixel(), 621 pEvent->bytesPerLine(), 622 Rmask, Gmask, Bmask, 0); 623 LogFlowFunc(("Created VRAM surface %p\n", m_pSurfVRAM)); 624 if (m_pSurfVRAM == NULL) 625 { 626 bFallback = true; 608 627 } 609 628 } … … 616 635 617 636 /* close SDL so we can init it again */ 618 if (m Screen)637 if (m_pScreen) 619 638 { 620 639 X11ScreenSaverSettingsSave(); 621 SDL_QuitSubSystem 640 SDL_QuitSubSystem(SDL_INIT_VIDEO); 622 641 X11ScreenSaverSettingsRestore(); 623 m Screen = NULL;642 m_pScreen = NULL; 624 643 } 625 644 626 645 /* 627 * initialize the SDL library, use its super hack to integrate it with our 628 * client window 646 * initialize the SDL library, use its super hack to integrate it with our client window 629 647 */ 630 648 static char sdlHack[64]; 631 LogFlowFunc (("Using client window 0x%08lX to initialize SDL\n", 632 mView->viewport()->winId())); 649 LogFlowFunc(("Using client window 0x%08lX to initialize SDL\n", m_pMachineView->viewport()->winId())); 633 650 /* Note: SDL_WINDOWID must be decimal (not hex) to work on Win32 */ 634 sprintf (sdlHack, "SDL_WINDOWID=%lu", mView->viewport()->winId());635 putenv 651 sprintf(sdlHack, "SDL_WINDOWID=%lu", m_pMachineView->viewport()->winId()); 652 putenv(sdlHack); 636 653 X11ScreenSaverSettingsSave(); 637 int rc = SDL_InitSubSystem 654 int rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); 638 655 X11ScreenSaverSettingsRestore(); 639 AssertMsg 656 AssertMsg(rc == 0, ("SDL initialization failed: %s\n", SDL_GetError())); 640 657 NOREF(rc); 641 658 642 659 #ifdef Q_WS_X11 643 660 /* undo signal redirections from SDL, it'd steal keyboard events from us! */ 644 signal 645 signal 646 #endif 647 648 LogFlowFunc (("Setting SDL video mode to %d x %d\n", mWdt, mHgt));661 signal(SIGINT, SIG_DFL); 662 signal(SIGQUIT, SIG_DFL); 663 #endif 664 665 LogFlowFunc(("Setting SDL video mode to %d x %d\n", m_width, m_height)); 649 666 650 667 /* Pixel format is RGB in any case */ 651 mPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 652 653 mScreen = SDL_SetVideoMode (mWdt, mHgt, 0, 654 SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL); 655 AssertMsg (mScreen, ("SDL video mode could not be set!\n")); 656 } 657 658 #endif 659 660 // 661 // VBoxDDRAWFrameBuffer class 662 ///////////////////////////////////////////////////////////////////////////// 668 m_uPixelFormat = FramebufferPixelFormat_FOURCC_RGB; 669 670 m_pScreen = SDL_SetVideoMode(m_width, m_height, 0, SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL); 671 AssertMsg(m_pScreen, ("SDL video mode could not be set!\n")); 672 } 673 #endif 663 674 664 675 #if defined (VBOX_GUI_USE_DDRAW) 665 666 676 /* The class is defined in VBoxFBDDRAW.cpp */ 667 668 #endif 669 670 // 671 // VBoxQuartz2DFrameBuffer class 672 ///////////////////////////////////////////////////////////////////////////// 677 #endif 673 678 674 679 #if defined (VBOX_GUI_USE_QUARTZ2D) 675 676 680 /* The class is defined in VBoxQuartz2D.cpp */ 677 678 #endif 681 #endif 682 #endif -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxFrameBuffer class and subclasses declarations4 * UIFrameBuffer class and subclasses declarations 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef ___VBoxFrameBuffer_h___ 24 #define ___VBoxFrameBuffer_h___ 23 #ifndef ___UIFrameBuffer_h___ 24 #define ___UIFrameBuffer_h___ 25 26 /* Global includes */ 27 //#include <QImage> 28 #include <QPixmap> 29 //#include <QMutex> 30 #include <QPaintEvent> 31 //#include <QMoveEvent> 32 //#if defined (VBOX_GUI_USE_QGL) 33 //#include "VBoxFBOverlay.h" 34 //#endif 35 36 /* Local includes */ 25 37 #include "COMDefs.h" 26 38 #include <iprt/critsect.h> 27 39 28 /* Qt includes */ 29 #include <QImage> 30 #include <QPixmap> 31 #include <QMutex> 32 #include <QPaintEvent> 33 #include <QMoveEvent> 34 #if defined (VBOX_GUI_USE_QGL) 35 #include "VBoxFBOverlay.h" 36 #endif 37 38 #if defined (VBOX_GUI_USE_SDL) 39 #include <SDL.h> 40 #include <signal.h> 41 #endif 42 43 #if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW) 40 //#if defined (VBOX_GUI_USE_SDL) 41 //#include <SDL.h> 42 //#include <signal.h> 43 //#endif 44 45 //#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW) 44 46 // VBox/cdefs.h defines these: 45 #undef LOWORD 46 #undef HIWORD 47 #undef LOBYTE 48 #undef HIBYTE 49 #include <ddraw.h> 50 #endif 51 52 class VBoxConsoleView; 53 54 ///////////////////////////////////////////////////////////////////////////// 47 //#undef LOWORD 48 //#undef HIWORD 49 //#undef LOBYTE 50 //#undef HIBYTE 51 //#include <ddraw.h> 52 //#endif 53 54 class UIMachineView; 55 55 56 56 /** 57 57 * Frame buffer resize event. 58 58 */ 59 class VBoxResizeEvent : public QEvent60 { 61 public: 62 63 VBoxResizeEvent (ulong aPixelFormat, uchar *aVRAM,64 ulong aBitsPerPixel, ulong aBytesPerLine,65 ulong aWidth, ulong aHeight) :66 QEvent ((QEvent::Type) VBoxDefs::ResizeEventType),67 mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),68 mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight) {}69 ulong pixelFormat() { return m PixelFormat; }70 uchar *VRAM() { return m VRAM; }71 ulong bitsPerPixel() { return m BitsPerPixel; }72 ulong bytesPerLine() { return m BytesPerLine; }73 ulong width() { return m Width; }74 ulong height() { return m Height; }75 76 private: 77 78 ulong m PixelFormat;79 uchar *m VRAM;80 ulong m BitsPerPixel;81 ulong m BytesPerLine;82 ulong m Width;83 ulong m Height;59 class UIResizeEvent : public QEvent 60 { 61 public: 62 63 UIResizeEvent(ulong uPixelFormat, uchar *pVRAM, 64 ulong uBitsPerPixel, ulong uBytesPerLine, 65 ulong uWidth, ulong uHeight) 66 : QEvent((QEvent::Type)VBoxDefs::ResizeEventType) 67 , m_uPixelFormat(uPixelFormat), m_pVRAM(pVRAM), m_uBitsPerPixel(uBitsPerPixel) 68 , m_uBytesPerLine(uBytesPerLine), m_uWidth(uWidth), m_uHeight(uHeight) {} 69 ulong pixelFormat() { return m_uPixelFormat; } 70 uchar *VRAM() { return m_pVRAM; } 71 ulong bitsPerPixel() { return m_uBitsPerPixel; } 72 ulong bytesPerLine() { return m_uBytesPerLine; } 73 ulong width() { return m_uWidth; } 74 ulong height() { return m_uHeight; } 75 76 private: 77 78 ulong m_uPixelFormat; 79 uchar *m_pVRAM; 80 ulong m_uBitsPerPixel; 81 ulong m_uBytesPerLine; 82 ulong m_uWidth; 83 ulong m_uHeight; 84 84 }; 85 85 … … 87 87 * Frame buffer repaint event. 88 88 */ 89 class VBoxRepaintEvent : public QEvent 90 { 91 public: 92 VBoxRepaintEvent (int iX, int iY, int iW, int iH) : 93 QEvent ((QEvent::Type) VBoxDefs::RepaintEventType), 94 ex (iX), ey (iY), ew (iW), eh (iH) 95 {} 96 int x() { return ex; } 97 int y() { return ey; } 98 int width() { return ew; } 99 int height() { return eh; } 100 private: 101 int ex, ey, ew, eh; 89 class UIRepaintEvent : public QEvent 90 { 91 public: 92 93 UIRepaintEvent(int iX, int iY, int iW, int iH) 94 : QEvent((QEvent::Type)VBoxDefs::RepaintEventType) 95 , m_iX(iX), m_iY(iY), m_iW(iW), m_iH(iH) {} 96 int x() { return m_iX; } 97 int y() { return m_iY; } 98 int width() { return m_iW; } 99 int height() { return m_iH; } 100 101 private: 102 103 int m_iX, m_iY, m_iW, m_iH; 102 104 }; 103 105 … … 105 107 * Frame buffer set region event. 106 108 */ 107 class VBoxSetRegionEvent : public QEvent 108 { 109 public: 110 VBoxSetRegionEvent (const QRegion &aReg) 111 : QEvent ((QEvent::Type) VBoxDefs::SetRegionEventType) 112 , mReg (aReg) {} 113 QRegion region() { return mReg; } 114 private: 115 QRegion mReg; 116 }; 117 118 ///////////////////////////////////////////////////////////////////////////// 109 class UISetRegionEvent : public QEvent 110 { 111 public: 112 113 UISetRegionEvent(const QRegion ®ion) 114 : QEvent((QEvent::Type)VBoxDefs::SetRegionEventType) 115 , m_region(region) {} 116 QRegion region() { return m_region; } 117 118 private: 119 120 QRegion m_region; 121 }; 119 122 120 123 /** … … 139 142 * See IFramebuffer documentation for more info. 140 143 */ 141 142 class VBoxFrameBuffer : VBOX_SCRIPTABLE_IMPL(IFramebuffer) 143 { 144 public: 145 146 VBoxFrameBuffer (VBoxConsoleView *aView); 147 virtual ~VBoxFrameBuffer(); 144 class UIFrameBuffer : VBOX_SCRIPTABLE_IMPL(IFramebuffer) 145 { 146 public: 147 148 UIFrameBuffer(UIMachineView *aView); 149 virtual ~UIFrameBuffer(); 148 150 149 151 NS_DECL_ISUPPORTS 150 152 151 153 #if defined (Q_OS_WIN32) 152 153 154 STDMETHOD_(ULONG, AddRef)() 154 155 { 155 return ::InterlockedIncrement (&refcnt);156 return ::InterlockedIncrement(&m_iRefCnt); 156 157 } 157 158 158 159 STDMETHOD_(ULONG, Release)() 159 160 { 160 long cnt = ::InterlockedDecrement (&refcnt);161 long cnt = ::InterlockedDecrement(&m_iRefCnt); 161 162 if (cnt == 0) 162 163 delete this; … … 164 165 } 165 166 #endif 167 166 168 VBOX_SCRIPTABLE_DISPATCH_IMPL(IFramebuffer) 167 169 168 / / IFramebuffer COM methods169 STDMETHOD(COMGETTER(Address)) (BYTE ** aAddress);170 STDMETHOD(COMGETTER(Width)) (ULONG * aWidth);171 STDMETHOD(COMGETTER(Height)) (ULONG * aHeight);172 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG * aBitsPerPixel);173 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG * aBytesPerLine);174 STDMETHOD(COMGETTER(PixelFormat)) (ULONG * aPixelFormat);175 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL * aUsesGuestVRAM);176 STDMETHOD(COMGETTER(HeightReduction)) (ULONG * aHeightReduction);177 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay ** aOverlay);178 STDMETHOD(COMGETTER(WinId)) (ULONG64 * winId);170 /* IFramebuffer COM methods */ 171 STDMETHOD(COMGETTER(Address)) (BYTE **ppAddress); 172 STDMETHOD(COMGETTER(Width)) (ULONG *puWidth); 173 STDMETHOD(COMGETTER(Height)) (ULONG *puHeight); 174 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *puBitsPerPixel); 175 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *puBytesPerLine); 176 STDMETHOD(COMGETTER(PixelFormat)) (ULONG *puPixelFormat); 177 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *pbUsesGuestVRAM); 178 STDMETHOD(COMGETTER(HeightReduction)) (ULONG *puHeightReduction); 179 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **ppOverlay); 180 STDMETHOD(COMGETTER(WinId)) (ULONG64 *pWinId); 179 181 180 182 STDMETHOD(Lock)(); 181 183 STDMETHOD(Unlock)(); 182 184 183 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,184 BYTE * aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,185 ULONG aWidth, ULONG aHeight,186 BOOL * aFinished);187 188 STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,189 BOOL * aSupported);190 191 STDMETHOD(GetVisibleRegion)(BYTE * aRectangles, ULONG aCount, ULONG *aCountCopied);192 STDMETHOD(SetVisibleRegion)(BYTE * aRectangles, ULONG aCount);185 STDMETHOD(RequestResize) (ULONG uScreenId, ULONG uPixelFormat, 186 BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine, 187 ULONG uWidth, ULONG uHeight, 188 BOOL *pbFinished); 189 190 STDMETHOD(VideoModeSupported) (ULONG uWidth, ULONG uHeight, ULONG uBPP, 191 BOOL *pbSupported); 192 193 STDMETHOD(GetVisibleRegion)(BYTE *pRectangles, ULONG uCount, ULONG *puCountCopied); 194 STDMETHOD(SetVisibleRegion)(BYTE *pRectangles, ULONG uCount); 193 195 194 196 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand); 195 197 196 ulong width() { return m Wdt; }197 ulong height() { return m Hgt; }198 ulong width() { return m_width; } 199 ulong height() { return m_height; } 198 200 199 201 virtual ulong pixelFormat() … … 207 209 } 208 210 209 void lock() { RTCritSectEnter(&m CritSect); }210 void unlock() { RTCritSectLeave(&m CritSect); }211 void lock() { RTCritSectEnter(&m_critSect); } 212 void unlock() { RTCritSectLeave(&m_critSect); } 211 213 212 214 virtual uchar *address() = 0; … … 218 220 * VM display viewport needs to be repainted on the host screen. 219 221 */ 220 virtual void paintEvent (QPaintEvent *pe) = 0;222 virtual void paintEvent(QPaintEvent *pEvent) = 0; 221 223 222 224 /** 223 225 * Called on the GUI thread (from VBoxConsoleView) after it gets a 224 * VBoxResizeEvent posted from the RequestResize() method implementation.226 * UIResizeEvent posted from the RequestResize() method implementation. 225 227 */ 226 virtual void resizeEvent (VBoxResizeEvent *re)227 { 228 m Wdt = re->width();229 m Hgt = re->height();228 virtual void resizeEvent(UIResizeEvent *pEvent) 229 { 230 m_width = pEvent->width(); 231 m_height = pEvent->height(); 230 232 } 231 233 … … 234 236 * window is moved. 235 237 */ 236 virtual void moveEvent (QMoveEvent * /*me*/) {}238 virtual void moveEvent(QMoveEvent * /* pEvent */) {} 237 239 238 240 #ifdef VBOX_WITH_VIDEOHWACCEL … … 242 244 virtual void doProcessVHWACommand(QEvent * pEvent); 243 245 244 virtual void viewportResized(QResizeEvent * /* re*/){}245 246 virtual void viewportScrolled(int /* dx*/, int /*dy*/){}246 virtual void viewportResized(QResizeEvent * /* pEvent */) {} 247 248 virtual void viewportScrolled(int /* iX */, int /* iY */) {} 247 249 #endif 248 250 249 251 protected: 250 252 251 VBoxConsoleView *mView;252 RTCRITSECT m CritSect;253 int m Wdt;254 int m Hgt;255 uint64_t m WinId;253 UIMachineView *m_pMachineView; 254 RTCRITSECT m_critSect; 255 int m_width; 256 int m_height; 257 uint64_t m_uWinId; 256 258 257 259 #if defined (Q_OS_WIN32) 258 260 private: 259 long refcnt; 260 #endif 261 }; 262 263 ///////////////////////////////////////////////////////////////////////////// 261 262 long m_iRefCnt; 263 #endif 264 }; 264 265 265 266 #if defined (VBOX_GUI_USE_QIMAGE) 266 267 class VBoxQImageFrameBuffer : public VBoxFrameBuffer 268 { 269 public: 270 271 VBoxQImageFrameBuffer (VBoxConsoleView *aView); 272 273 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY, 274 ULONG aW, ULONG aH); 275 276 ulong pixelFormat() { return mPixelFormat; } 277 bool usesGuestVRAM() { return mUsesGuestVRAM; } 278 279 uchar *address() { return mImg.bits(); } 280 ulong bitsPerPixel() { return mImg.depth(); } 281 ulong bytesPerLine() { return mImg.bytesPerLine(); } 282 283 void paintEvent (QPaintEvent *pe); 284 void resizeEvent (VBoxResizeEvent *re); 285 286 private: 287 288 QPixmap mPM; 289 QImage mImg; 290 ulong mPixelFormat; 291 bool mUsesGuestVRAM; 292 }; 293 294 #endif 295 296 ///////////////////////////////////////////////////////////////////////////// 297 267 class UIFrameBufferQImage : public UIFrameBuffer 268 { 269 public: 270 271 UIFrameBufferQImage(UIMachineView *pMachineView); 272 273 STDMETHOD(NotifyUpdate) (ULONG uX, ULONG uY, ULONG uW, ULONG uH); 274 275 ulong pixelFormat() { return m_uPixelFormat; } 276 bool usesGuestVRAM() { return m_bUsesGuestVRAM; } 277 278 uchar *address() { return m_img.bits(); } 279 ulong bitsPerPixel() { return m_img.depth(); } 280 ulong bytesPerLine() { return m_img.bytesPerLine(); } 281 282 void paintEvent (QPaintEvent *pEvent); 283 void resizeEvent (UIResizeEvent *pEvent); 284 285 private: 286 287 QPixmap m_PM; 288 QImage m_img; 289 ulong m_uPixelFormat; 290 bool m_bUsesGuestVRAM; 291 }; 292 #endif 293 294 #if 0 298 295 #if defined (VBOX_GUI_USE_QGL) 299 300 class VBoxQGLFrameBuffer : public VBoxFrameBuffer 301 { 302 public: 303 304 VBoxQGLFrameBuffer (VBoxConsoleView *aView); 305 306 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY, 307 ULONG aW, ULONG aH); 296 class UIFrameBufferQGL : public UIFrameBuffer 297 { 298 public: 299 300 UIFrameBufferQGL(UIMachineView *pMachineView); 301 302 STDMETHOD(NotifyUpdate) (ULONG uX, ULONG uY, ULONG uW, ULONG uH); 308 303 #ifdef VBOXQGL_PROF_BASE 309 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat, 310 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine, 311 ULONG aWidth, ULONG aHeight, 312 BOOL *aFinished); 304 STDMETHOD(RequestResize) (ULONG uScreenId, ULONG uPixelFormat, 305 BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine, 306 ULONG uWidth, ULONG uHeight, BOOL *pbFinished); 313 307 #endif 314 308 315 309 #ifdef VBOX_WITH_VIDEOHWACCEL 316 STDMETHOD(ProcessVHWACommand)(BYTE *p Command);310 STDMETHOD(ProcessVHWACommand)(BYTE *pbCommand); 317 311 #endif 318 312 … … 324 318 ulong bytesPerLine() { return vboxWidget()->vboxBytesPerLine(); } 325 319 326 void paintEvent (QPaintEvent *pe); 327 void resizeEvent (VBoxResizeEvent *re); 328 void doProcessVHWACommand(QEvent * pEvent); 329 330 private: 331 // void vboxMakeCurrent(); 332 class VBoxGLWidget * vboxWidget(); 333 334 class VBoxVHWACommandElementProcessor mCmdPipe; 335 }; 336 337 #endif 338 339 ///////////////////////////////////////////////////////////////////////////// 320 void paintEvent (QPaintEvent *pEvent); 321 void resizeEvent (UIResizeEvent *pEvent); 322 void doProcessVHWACommand(QEvent *pEvent); 323 324 private: 325 326 class VBoxGLWidget* vboxWidget(); 327 328 class VBoxVHWACommandElementProcessor m_cmdPipe; 329 }; 330 #endif 340 331 341 332 #if defined (VBOX_GUI_USE_SDL) 342 343 class VBoxSDLFrameBuffer : public VBoxFrameBuffer 344 { 345 public: 346 347 VBoxSDLFrameBuffer (VBoxConsoleView *aView); 348 virtual ~VBoxSDLFrameBuffer(); 349 350 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY, 351 ULONG aW, ULONG aH); 352 353 uchar *address() 354 { 355 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen; 356 return surf ? (uchar *) (uintptr_t) surf->pixels : 0; 333 class UIFrameBufferSDL : public UIFrameBuffer 334 { 335 public: 336 337 UIFrameBufferSDL (VBoxConsoleView *pMachineView); 338 virtual ~UIFrameBufferSDL(); 339 340 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY, ULONG aW, ULONG aH); 341 342 uchar* address() 343 { 344 SDL_Surface *surf = m_pSurfVRAM ? m_pSurfVRAM : m_pScreen; 345 return surf ? (uchar*) (uintptr_t) surf->pixels : 0; 357 346 } 358 347 359 348 ulong bitsPerPixel() 360 349 { 361 SDL_Surface *surf = m SurfVRAM ? mSurfVRAM : mScreen;350 SDL_Surface *surf = m_pSurfVRAM ? m_pSurfVRAM : m_pScreen; 362 351 return surf ? surf->format->BitsPerPixel : 0; 363 352 } … … 365 354 ulong bytesPerLine() 366 355 { 367 SDL_Surface *surf = m SurfVRAM ? mSurfVRAM : mScreen;356 SDL_Surface *surf = m_pSurfVRAM ? m_pSurfVRAM : m_pScreen; 368 357 return surf ? surf->pitch : 0; 369 358 } … … 371 360 ulong pixelFormat() 372 361 { 373 return m PixelFormat;362 return m_uPixelFormat; 374 363 } 375 364 376 365 bool usesGuestVRAM() 377 366 { 378 return mSurfVRAM != NULL; 379 } 380 381 void paintEvent (QPaintEvent *pe); 382 void resizeEvent (VBoxResizeEvent *re); 383 384 private: 385 386 SDL_Surface *mScreen; 387 SDL_Surface *mSurfVRAM; 388 389 ulong mPixelFormat; 390 }; 391 392 #endif 393 394 ///////////////////////////////////////////////////////////////////////////// 367 return m_pSurfVRAM != NULL; 368 } 369 370 void paintEvent(QPaintEvent *pEvent); 371 void resizeEvent(UIResizeEvent *pEvent); 372 373 private: 374 375 SDL_Surface *m_pScreen; 376 SDL_Surface *m_pSurfVRAM; 377 378 ulong m_uPixelFormat; 379 }; 380 #endif 395 381 396 382 #if defined (VBOX_GUI_USE_DDRAW) 397 398 class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer 399 { 400 public: 401 402 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView); 403 virtual ~VBoxDDRAWFrameBuffer(); 404 405 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY, 406 ULONG aW, ULONG aH); 407 408 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; } 409 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; } 410 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; } 411 412 ulong pixelFormat() { return mPixelFormat; }; 413 414 bool usesGuestVRAM() { return mUsesGuestVRAM; } 415 416 void paintEvent (QPaintEvent *pe); 417 void resizeEvent (VBoxResizeEvent *re); 418 void moveEvent (QMoveEvent *me); 383 class UIFrameBufferDDRAW : public UIFrameBuffer 384 { 385 public: 386 387 UIFrameBufferDDRAW(UIMachineView *pMachineView); 388 virtual ~UIFrameBufferDDRAW(); 389 390 STDMETHOD(NotifyUpdate) (ULONG uX, ULONG uY, ULONG uW, ULONG uH); 391 392 uchar* address() { return (uchar*) m_surfaceDesc.lpSurface; } 393 ulong bitsPerPixel() { return m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount; } 394 ulong bytesPerLine() { return (ulong) m_surfaceDesc.lPitch; } 395 396 ulong pixelFormat() { return m_uPixelFormat; }; 397 398 bool usesGuestVRAM() { return m_bUsesGuestVRAM; } 399 400 void paintEvent(QPaintEvent *pEvent); 401 void resizeEvent(UIResizeEvent *pEvent); 402 void moveEvent(QMoveEvent *pEvent); 419 403 420 404 private: … … 422 406 void releaseObjects(); 423 407 424 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,425 ULONG aBitsPerPixel, ULONG aBytesPerLine,426 ULONG aWidth, ULONG aHeight);408 bool createSurface(ULONG uPixelFormat, uchar *pvVRAM, 409 ULONG uBitsPerPixel, ULONG uBytesPerLine, 410 ULONG uWidth, ULONG uHeight); 427 411 void deleteSurface(); 428 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h); 429 void getWindowPosition (void); 430 431 LPDIRECTDRAW7 mDDRAW; 432 LPDIRECTDRAWCLIPPER mClipper; 433 LPDIRECTDRAWSURFACE7 mSurface; 434 DDSURFACEDESC2 mSurfaceDesc; 435 LPDIRECTDRAWSURFACE7 mPrimarySurface; 436 437 ulong mPixelFormat; 438 439 bool mUsesGuestVRAM; 440 441 int mWndX; 442 int mWndY; 443 444 bool mSynchronousUpdates; 445 }; 446 447 #endif 448 449 ///////////////////////////////////////////////////////////////////////////// 412 void drawRect(ULONG uX, ULONG uY, ULONG uW, ULONG uH); 413 void getWindowPosition(void); 414 415 LPDIRECTDRAW7 m_DDRAW; 416 LPDIRECTDRAWCLIPPER m_clipper; 417 LPDIRECTDRAWSURFACE7 m_surface; 418 DDSURFACEDESC2 m_surfaceDesc; 419 LPDIRECTDRAWSURFACE7 m_primarySurface; 420 421 ulong m_uPixelFormat; 422 423 bool m_bUsesGuestVRAM; 424 425 int m_iWndX; 426 int m_iWndY; 427 428 bool m_bSynchronousUpdates; 429 }; 430 #endif 450 431 451 432 #if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D) 452 453 433 #include <Carbon/Carbon.h> 454 434 455 class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer 456 { 457 public: 458 459 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView); 460 virtual ~VBoxQuartz2DFrameBuffer (); 461 462 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY, 463 ULONG aW, ULONG aH); 464 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount); 465 466 uchar *address() { return mDataAddress; } 467 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); } 468 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); } 469 ulong pixelFormat() { return mPixelFormat; }; 470 bool usesGuestVRAM() { return mBitmapData == NULL; } 471 472 const CGImageRef imageRef() const { return mImage; } 473 474 void paintEvent (QPaintEvent *pe); 475 void resizeEvent (VBoxResizeEvent *re); 435 class UIFrameBufferQuartz2D : public UIFrameBuffer 436 { 437 public: 438 439 UIFrameBufferQuartz2D(UIMachineView *pMachineView); 440 virtual ~UIFrameBufferQuartz2D(); 441 442 STDMETHOD (NotifyUpdate) (ULONG uX, ULONG uY, ULONG uW, ULONG uH); 443 STDMETHOD (SetVisibleRegion) (BYTE *pRectangles, ULONG uCount); 444 445 uchar* address() { return m_pDataAddress; } 446 ulong bitsPerPixel() { return CGImageGetBitsPerPixel(m_image); } 447 ulong bytesPerLine() { return CGImageGetBytesPerRow(m_image); } 448 ulong pixelFormat() { return m_uPixelFormat; }; 449 bool usesGuestVRAM() { return m_pBitmapData == NULL; } 450 451 const CGImageRef imageRef() const { return m_image; } 452 453 void paintEvent(QPaintEvent *pEvent); 454 void resizeEvent(UIResizeEvent *pEvent); 476 455 477 456 #ifndef QT_MAC_USE_COCOA … … 483 462 void clean(); 484 463 485 uchar *m DataAddress;486 void *m BitmapData;487 ulong m PixelFormat;488 CGImageRef m Image;464 uchar *m_pDataAddress; 465 void *m_pBitmapData; 466 ulong m_uPixelFormat; 467 CGImageRef m_image; 489 468 typedef struct 490 469 { … … 516 495 #endif /* QT_MAC_USE_COCOA */ 517 496 }; 518 519 497 #endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */ 520 521 #endif // !___VBoxFrameBuffer_h___ 498 #endif 499 500 #endif // !___UIFrameBuffer_h___ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass implementation4 * UIMachine class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010 Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 /* Global includes */24 #ifdef VBOX_WITH_PRECOMPILED_HEADERS25 # include "precomp.h"26 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */27 #include <QActionGroup>28 #include <QDesktopWidget>29 #include <QDir>30 #include <QFileInfo>31 #include <QMenuBar>32 #include <QProgressBar>33 #include <QTimer>34 35 #ifdef Q_WS_X1136 # include <QX11Info>37 #endif38 #ifdef Q_WS_MAC39 # include <QPainter>40 #endif41 42 23 /* Local includes */ 43 #include "QIFileDialog.h"44 #include "QIHotKeyEdit.h"45 #include "QIHttp.h"46 #include "QIStateIndicator.h"47 #include "QIStatusBar.h"48 #include "QIWidgetValidator.h"49 #include "QIHotKeyEdit.h"50 #include "VBoxConsoleWnd.h"51 #include "VBoxConsoleView.h"52 #include "VBoxCloseVMDlg.h"53 #include "VBoxDownloaderWgt.h"54 24 #include "VBoxGlobal.h" 55 #include "VBoxMediaManagerDlg.h" 56 #include "VBoxMiniToolBar.h" 57 #include "VBoxProblemReporter.h" 58 #include "VBoxTakeSnapshotDlg.h" 59 #include "UIFirstRunWzd.h" 60 #include "VBoxVMSettingsNetwork.h" 61 #include "VBoxVMSettingsSF.h" 62 #include "VBoxVMInformationDlg.h" 63 64 #ifdef Q_WS_X11 65 # include <X11/Xlib.h> 66 # include <XKeyboard.h> 67 #endif 68 #ifdef Q_WS_MAC 69 # include "VBoxUtils.h" 70 # include "VBoxIChatTheaterWrapper.h" 71 # include <ApplicationServices/ApplicationServices.h> 72 #endif 73 #ifdef VBOX_WITH_DEBUGGER_GUI 74 # include <VBox/err.h> 75 # include <iprt/ldr.h> 76 #endif 77 78 #include <VBox/VMMDev.h> /** @todo @bugref{4084} */ 79 #include <iprt/buildconfig.h> 80 #include <iprt/param.h> 81 #include <iprt/path.h> 82 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 83 84 /* Global forwards */ 85 extern void qt_set_sequence_auto_mnemonic (bool on); 86 87 /** class StatusTipEvent 88 * 89 * The StatusTipEvent class is an auxiliary QEvent class 90 * for carrying statusTip text of non-QAction menu item's. 91 * This event is posted then the menu item is highlighted but 92 * processed later in VBoxConsoleWnd::event() handler to 93 * avoid statusBar messaging collisions. 94 */ 95 class StatusTipEvent : public QEvent 96 { 97 public: 98 enum { Type = QEvent::User + 10 }; 99 StatusTipEvent (const QString &aTip) 100 : QEvent ((QEvent::Type) Type), mTip (aTip) {} 101 102 QString mTip; 103 }; 104 105 class VBoxAdditionsDownloader : public VBoxDownloaderWgt 106 { 107 Q_OBJECT; 108 109 public: 110 111 VBoxAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 112 : VBoxDownloaderWgt (aSource, aTarget) 113 , mAction (aAction) 114 { 115 mAction->setEnabled (false); 116 retranslateUi(); 117 } 118 119 void start() 120 { 121 acknowledgeStart(); 122 } 25 #include "UIMachine.h" 26 #include "UIActionsPool.h" 27 #include "UIMachineLogic.h" 28 29 class UIVisualState : public QObject 30 { 31 Q_OBJECT; 32 33 public: 34 35 UIVisualState(QObject *pParent) : QObject(pParent), m_pMachineLogic(0) 36 { 37 /* Connect state-change handler */ 38 connect(this, SIGNAL(sigChangeVisualState(UIVisualStateType)), parent(), SLOT(sltChangeVisualState(UIVisualStateType))); 39 } 40 41 signals: 42 43 void sigChangeVisualState(UIVisualStateType visualStateType); 123 44 124 45 protected: 125 46 126 void retranslateUi() 127 { 128 mCancelButton->setText (tr ("Cancel")); 129 mProgressBar->setToolTip (tr ("Downloading the VirtualBox Guest Additions " 130 "CD image from <nobr><b>%1</b>...</nobr>") 131 .arg (mSource.toString())); 132 mCancelButton->setToolTip (tr ("Cancel the VirtualBox Guest " 133 "Additions CD image download")); 47 UIMachineLogic *m_pMachineLogic; 48 }; 49 50 class UIVisualStateNormal : public UIVisualState 51 { 52 Q_OBJECT; 53 54 public: 55 56 UIVisualStateNormal(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool) 57 : UIVisualState(pParent) 58 { 59 /* Connect action handlers */ 60 connect(pActionsPool->action(UIActionIndex_Toggle_Fullscreen), SIGNAL(triggered(bool)), 61 this, SLOT(sltGoToFullscreenMode())); 62 connect(pActionsPool->action(UIActionIndex_Toggle_Seamless), SIGNAL(triggered(bool)), 63 this, SLOT(sltGoToSeamlessMode())); 64 65 /* Create state logic */ 66 m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Normal); 134 67 } 135 68 136 69 private slots: 137 70 138 void downloadFinished (bool aError) 139 { 140 if (aError) 141 VBoxDownloaderWgt::downloadFinished (aError); 142 else 71 void sltGoToFullscreenMode() 72 { 73 emit sigChangeVisualState(UIVisualStateType_Fullscreen); 74 } 75 76 void sltGoToSeamlessMode() 77 { 78 emit sigChangeVisualState(UIVisualStateType_Seamless); 79 } 80 }; 81 82 class UIVisualStateFullscreen : public UIVisualState 83 { 84 Q_OBJECT; 85 86 public: 87 88 UIVisualStateFullscreen(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool) 89 : UIVisualState(pParent) 90 { 91 /* Connect action handlers */ 92 connect(pActionsPool->action(UIActionIndex_Toggle_Fullscreen), SIGNAL(triggered(bool)), 93 this, SLOT(sltGoToNormalMode())); 94 connect(pActionsPool->action(UIActionIndex_Toggle_Seamless), SIGNAL(triggered(bool)), 95 this, SLOT(sltGoToSeamlessMode())); 96 97 /* Create state logic */ 98 m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Fullscreen); 99 } 100 101 private slots: 102 103 void sltGoToNormalMode() 104 { 105 emit sigChangeVisualState(UIVisualStateType_Normal); 106 } 107 108 void sltGoToSeamlessMode() 109 { 110 emit sigChangeVisualState(UIVisualStateType_Seamless); 111 } 112 }; 113 114 class UIVisualStateSeamless : public UIVisualState 115 { 116 Q_OBJECT; 117 118 public: 119 120 UIVisualStateSeamless(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool) 121 : UIVisualState(pParent) 122 { 123 /* Connect action handlers */ 124 connect(pActionsPool->action(UIActionIndex_Toggle_Fullscreen), SIGNAL(triggered(bool)), 125 this, SLOT(sltGoToFullscreenMode())); 126 connect(pActionsPool->action(UIActionIndex_Toggle_Seamless), SIGNAL(triggered(bool)), 127 this, SLOT(sltGoToNormalMode())); 128 129 /* Create state logic */ 130 m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Seamless); 131 } 132 133 private slots: 134 135 void sltGoToFullscreenMode() 136 { 137 emit sigChangeVisualState(UIVisualStateType_Fullscreen); 138 } 139 140 void sltGoToNormalMode() 141 { 142 emit sigChangeVisualState(UIVisualStateType_Normal); 143 } 144 }; 145 146 UIMachine::UIMachine(UIMachine **ppSelf, const CSession &session) 147 : QObject(0) 148 , m_session(session) 149 , m_pActionsPool(new UIActionsPool(this)) 150 , m_pVisualState(0) 151 { 152 /* Cache IMedium data: */ 153 vboxGlobal().startEnumeratingMedia(); 154 155 /* Check CSession object */ 156 AssertMsg(!m_session.isNull(), ("CSession is not set!\n")); 157 158 /* Storing self */ 159 if (ppSelf) 160 *ppSelf = this; 161 162 /* Enter default (normal) state */ 163 enterBaseVisualState(); 164 } 165 166 void UIMachine::sltChangeVisualState(UIVisualStateType visualStateType) 167 { 168 /* Delete previous state */ 169 delete m_pVisualState; 170 m_pVisualState = 0; 171 172 /* Create new state */ 173 switch (visualStateType) 174 { 175 case UIVisualStateType_Normal: 143 176 { 144 QByteArray receivedData (mHttp->readAll()); 145 /* Serialize the incoming buffer into the .iso image. */ 146 while (true) 147 { 148 QFile file (mTarget); 149 if (file.open (QIODevice::WriteOnly)) 150 { 151 file.write (receivedData); 152 file.close(); 153 if (vboxProblem().confirmMountAdditions (mSource.toString(), 154 QDir::toNativeSeparators (mTarget))) 155 vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 156 QTimer::singleShot (0, this, SLOT (suicide())); 157 break; 158 } 159 else 160 { 161 vboxProblem().message (window(), VBoxProblemReporter::Error, 162 tr ("<p>Failed to save the downloaded file as " 163 "<nobr><b>%1</b>.</nobr></p>") 164 .arg (QDir::toNativeSeparators (mTarget))); 165 } 166 167 QString target = QIFileDialog::getExistingDirectory ( 168 QFileInfo (mTarget).absolutePath(), this, 169 tr ("Select folder to save Guest Additions image to"), true); 170 if (target.isNull()) 171 QTimer::singleShot (0, this, SLOT (suicide())); 172 else 173 mTarget = QDir (target).absoluteFilePath (QFileInfo (mTarget).fileName()); 174 } 177 m_pVisualState = new UIVisualStateNormal(this, m_session, m_pActionsPool); 178 break; 175 179 } 176 } 177 178 void suicide() 179 { 180 QStatusBar *sb = qobject_cast <QStatusBar*> (parent()); 181 Assert (sb); 182 sb->removeWidget (this); 183 mAction->setEnabled (true); 184 VBoxDownloaderWgt::suicide(); 185 } 186 187 private: 188 189 bool confirmDownload() 190 { 191 return vboxProblem().confirmDownloadAdditions (mSource.toString(), 192 mHttp->lastResponse().contentLength()); 193 } 194 195 void warnAboutError (const QString &aError) 196 { 197 return vboxProblem().cannotDownloadGuestAdditions (mSource.toString(), aError); 198 } 199 200 QAction *mAction; 201 }; 202 203 struct MountTarget 204 { 205 MountTarget() : name (QString ("")), port (0), device (0), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 206 MountTarget (const QString &aName, LONG aPort, LONG aDevice) 207 : name (aName), port (aPort), device (aDevice), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 208 MountTarget (const QString &aName, LONG aPort, LONG aDevice, const QString &aId) 209 : name (aName), port (aPort), device (aDevice), id (aId), type (VBoxDefs::MediumType_Invalid) {} 210 MountTarget (const QString &aName, LONG aPort, LONG aDevice, VBoxDefs::MediumType aType) 211 : name (aName), port (aPort), device (aDevice), id (QString()), type (aType) {} 212 QString name; 213 LONG port; 214 LONG device; 215 QString id; 216 VBoxDefs::MediumType type; 217 }; 218 Q_DECLARE_METATYPE (MountTarget); 219 220 int searchMaxSnapshotIndex (const CMachine &aMachine, const CSnapshot &aSnapshot, const QString &aNameTemplate) 221 { 222 int maxIndex = 0; 223 QRegExp regExp (QString ("^") + aNameTemplate.arg ("([0-9]+)") + QString ("$")); 224 if (!aSnapshot.isNull()) 225 { 226 /* Check the current snapshot name */ 227 QString name = aSnapshot.GetName(); 228 int pos = regExp.indexIn (name); 229 if (pos != -1) 230 maxIndex = regExp.cap (1).toInt() > maxIndex ? regExp.cap (1).toInt() : maxIndex; 231 /* Traversing all the snapshot children */ 232 foreach (const CSnapshot &child, aSnapshot.GetChildren()) 180 case UIVisualStateType_Fullscreen: 233 181 { 234 int maxIndexOfChildren = searchMaxSnapshotIndex (aMachine, child, aNameTemplate);235 maxIndex = maxIndexOfChildren > maxIndex ? maxIndexOfChildren : maxIndex;182 m_pVisualState = new UIVisualStateFullscreen(this, m_session, m_pActionsPool); 183 break; 236 184 } 237 } 238 return maxIndex; 239 } 240 241 /** \class VBoxConsoleWnd 242 * 243 * The VBoxConsoleWnd class is a VM console window, one of two main VBox 244 * GUI windows. 245 * 246 * This window appears when the user starts the virtual machine. It 247 * contains the VBoxConsoleView widget that acts as a console of the 248 * running virtual machine. 249 */ 250 251 /** 252 * Constructs the VM console window. 253 * 254 * @param aSelf pointer to a variable where to store |this| right after 255 * this object's constructor is called (necessary to avoid 256 * recursion in VBoxGlobal::consoleWnd()) 257 */ 258 VBoxConsoleWnd::VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent, Qt::WindowFlags aFlags /* = Qt::Window */) 259 : QIWithRetranslateUI2 <QMainWindow> (aParent, aFlags) 260 /* Machine State */ 261 , mMachineState (KMachineState_Null) 262 /* Window Variables */ 263 , mConsoleStyle (0) 264 /* Menu Items */ 265 , mMainMenu (0) 266 , mVMMenu (0) 267 , mVMMenuMini (0) 268 , mDevicesMenu (0) 269 , mDevicesCDMenu (0) 270 , mDevicesFDMenu (0) 271 , mDevicesNetworkMenu (0) 272 , mDevicesSFMenu (0) 273 , mDevicesUSBMenu (0) 274 , mVmDisMouseIntegrMenu (0) 275 #if 0 /* TODO: Allow to setup status-bar! */ 276 , mDevicesVRDPMenu (0) 277 , mVmAutoresizeMenu (0) 278 #endif 279 #ifdef VBOX_WITH_DEBUGGER_GUI 280 , mDbgMenu (0) 281 #endif 282 , mHelpMenu (0) 283 /* Action Groups */ 284 , mRunningActions (0) 285 , mRunningOrPausedActions (0) 286 /* Machine Menu Actions */ 287 , mVmFullscreenAction (0) 288 , mVmSeamlessAction (0) 289 , mVmAutoresizeGuestAction (0) 290 , mVmAdjustWindowAction (0) 291 , mVmDisableMouseIntegrAction (0) 292 , mVmTypeCADAction (0) 293 #ifdef Q_WS_X11 294 , mVmTypeCABSAction (0) 295 #endif 296 , mVmTakeSnapshotAction (0) 297 , mVmShowInformationDlgAction (0) 298 , mVmResetAction (0) 299 , mVmPauseAction (0) 300 , mVmACPIShutdownAction (0) 301 , mVmCloseAction (0) 302 /* Device Menu Actions */ 303 , mDevicesNetworkDialogAction (0) 304 , mDevicesSFDialogAction (0) 305 , mDevicesSwitchVrdpSeparator (0) 306 , mDevicesSwitchVrdpAction (0) 307 , mDevicesInstallGuestToolsAction (0) 308 #ifdef VBOX_WITH_DEBUGGER_GUI 309 /* Debug Menu Actions */ 310 , mDbgStatisticsAction (0) 311 , mDbgCommandLineAction (0) 312 , mDbgLoggingAction (0) 313 #endif 314 /* Widgets */ 315 , mConsole (0) 316 , mMiniToolBar (0) 317 #ifdef VBOX_WITH_DEBUGGER_GUI 318 , mDbgGui (0) 319 , mDbgGuiVT (0) 320 #endif 321 /* LED Update Timer */ 322 , mIdleTimer (new QTimer (this)) 323 /* LEDs */ 324 , mHDLed (0) 325 , mCDLed (0) 326 #if 0 /* TODO: Allow to setup status-bar! */ 327 , mFDLed (0) 328 #endif 329 , mNetLed (0) 330 , mUSBLed (0) 331 , mSFLed (0) 332 , mVirtLed (0) 333 , mMouseLed (0) 334 , mHostkeyLed (0) 335 , mHostkeyLedContainer (0) 336 , mHostkeyName (0) 337 #if 0 /* TODO: Allow to setup status-bar! */ 338 , mVrdpLed (0) 339 , mAutoresizeLed (0) 340 #endif 341 , mIsOpenViewFinished (false) 342 , mIsFirstTimeStarted (false) 343 , mIsAutoSaveMedia (true) 344 , mNoAutoClose (false) 345 , mIsFullscreen (false) 346 , mIsSeamless (false) 347 , mIsSeamlessSupported (false) 348 , mIsGraphicsSupported (false) 349 , mIsWaitingModeResize (false) 350 , mWasMax (false) 351 { 352 if (aSelf) 353 *aSelf = this; 354 355 /* Cache IMedium data! */ 356 vboxGlobal().startEnumeratingMedia(); 357 358 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 359 /* The default application icon (will change to the VM-specific icon in 360 * openView()). On Win32, it's built-in to the executable. On Mac OS X the 361 * icon referenced in info.plist is used. */ 362 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 363 #endif 364 365 /* Ensure status bar is created */ 366 setStatusBar (new QIStatusBar (this)); 367 368 /* A group for all actions that are enabled only when the VM is running. 369 * Note that only actions whose enabled state depends exclusively on the 370 * execution state of the VM are added to this group. */ 371 mRunningActions = new QActionGroup (this); 372 mRunningActions->setExclusive (false); 373 374 /* A group for all actions that are enabled when the VM is running or 375 * paused. Note that only actions whose enabled state depends exclusively 376 * on the execution state of the VM are added to this group. */ 377 mRunningOrPausedActions = new QActionGroup (this); 378 mRunningOrPausedActions->setExclusive (false); 379 380 /* VM menu actions */ 381 mVmFullscreenAction = new QAction (this); 382 mVmFullscreenAction->setIcon (VBoxGlobal::iconSetOnOff ( 383 ":/fullscreen_on_16px.png", ":/fullscreen_16px.png", 384 ":/fullscreen_on_disabled_16px.png", ":/fullscreen_disabled_16px.png")); 385 mVmFullscreenAction->setCheckable (true); 386 387 mVmSeamlessAction = new QAction (this); 388 mVmSeamlessAction->setIcon (VBoxGlobal::iconSetOnOff ( 389 ":/seamless_on_16px.png", ":/seamless_16px.png", 390 ":/seamless_on_disabled_16px.png", ":/seamless_disabled_16px.png")); 391 mVmSeamlessAction->setCheckable (true); 392 393 mVmAutoresizeGuestAction = new QAction (mRunningActions); 394 mVmAutoresizeGuestAction->setIcon (VBoxGlobal::iconSetOnOff ( 395 ":/auto_resize_on_on_16px.png", ":/auto_resize_on_16px.png", 396 ":/auto_resize_on_on_disabled_16px.png", ":/auto_resize_on_disabled_16px.png")); 397 mVmAutoresizeGuestAction->setCheckable (true); 398 mVmAutoresizeGuestAction->setEnabled (false); 399 400 mVmAdjustWindowAction = new QAction (this); 401 mVmAdjustWindowAction->setIcon (VBoxGlobal::iconSet ( 402 ":/adjust_win_size_16px.png", ":/adjust_win_size_disabled_16px.png")); 403 404 mVmDisableMouseIntegrAction = new QAction (this); 405 mVmDisableMouseIntegrAction->setIcon (VBoxGlobal::iconSetOnOff ( 406 ":/mouse_can_seamless_on_16px.png", ":/mouse_can_seamless_16px.png", 407 ":/mouse_can_seamless_on_disabled_16px.png", ":/mouse_can_seamless_disabled_16px.png")); 408 mVmDisableMouseIntegrAction->setCheckable (true); 409 410 mVmTypeCADAction = new QAction (mRunningActions); 411 mVmTypeCADAction->setIcon (VBoxGlobal::iconSet ( 412 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 413 414 #if defined(Q_WS_X11) 415 mVmTypeCABSAction = new QAction (mRunningActions); 416 mVmTypeCABSAction->setIcon (VBoxGlobal::iconSet ( 417 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 418 #endif 419 420 mVmTakeSnapshotAction = new QAction (mRunningOrPausedActions); 421 mVmTakeSnapshotAction->setIcon (VBoxGlobal::iconSet ( 422 ":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png")); 423 424 mVmShowInformationDlgAction = new QAction (this); 425 mVmShowInformationDlgAction->setIcon (VBoxGlobal::iconSet ( 426 ":/session_info_16px.png", ":/session_info_disabled_16px.png")); 427 428 mVmResetAction = new QAction (mRunningActions); 429 mVmResetAction->setIcon (VBoxGlobal::iconSet ( 430 ":/reset_16px.png", ":/reset_disabled_16px.png")); 431 432 mVmPauseAction = new QAction (this); 433 mVmPauseAction->setIcon (VBoxGlobal::iconSet ( 434 ":/pause_16px.png", ":/pause_disabled_16px.png")); 435 mVmPauseAction->setCheckable (true); 436 437 mVmACPIShutdownAction = new QAction (mRunningActions); 438 mVmACPIShutdownAction->setIcon (VBoxGlobal::iconSet ( 439 ":/acpi_16px.png", ":/acpi_disabled_16px.png")); 440 441 mVmCloseAction = new QAction (this); 442 mVmCloseAction->setMenuRole (QAction::QuitRole); 443 mVmCloseAction->setIcon (VBoxGlobal::iconSet (":/exit_16px.png")); 444 445 /* Devices menu actions */ 446 mDevicesNetworkDialogAction = new QAction (mRunningOrPausedActions); 447 mDevicesNetworkDialogAction->setIcon (VBoxGlobal::iconSet ( 448 ":/nw_16px.png", ":/nw_disabled_16px.png")); 449 450 mDevicesSFDialogAction = new QAction (mRunningOrPausedActions); 451 mDevicesSFDialogAction->setIcon (VBoxGlobal::iconSet ( 452 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")); 453 454 mDevicesSwitchVrdpAction = new QAction (mRunningOrPausedActions); 455 mDevicesSwitchVrdpAction->setIcon (VBoxGlobal::iconSetOnOff ( 456 ":/vrdp_on_16px.png", ":/vrdp_16px.png", 457 ":/vrdp_on_disabled_16px.png", ":/vrdp_disabled_16px.png")); 458 mDevicesSwitchVrdpAction->setCheckable (true); 459 460 mDevicesInstallGuestToolsAction = new QAction (mRunningActions); 461 mDevicesInstallGuestToolsAction->setIcon (VBoxGlobal::iconSet ( 462 ":/guesttools_16px.png", ":/guesttools_disabled_16px.png")); 463 464 #ifdef VBOX_WITH_DEBUGGER_GUI 465 /* Debug menu actions */ 466 if (vboxGlobal().isDebuggerEnabled()) 467 { 468 mDbgStatisticsAction = new QAction (this); 469 mDbgCommandLineAction = new QAction (this); 470 if (vboxGlobal().getDebuggerModule()== NIL_RTLDRMOD) 185 case UIVisualStateType_Seamless: 471 186 { 472 mDbgStatisticsAction->setEnabled (false); 473 mDbgCommandLineAction->setEnabled (false); 474 } 475 mDbgLoggingAction = new QAction (this); 476 mDbgLoggingAction->setCheckable (true); 477 } 478 else 479 { 480 mDbgStatisticsAction = 0; 481 mDbgCommandLineAction = 0; 482 mDbgLoggingAction = 0; 483 } 484 #endif 485 486 /* Help menu actions */ 487 mHelpActions.setup (this); 488 489 /* Menu Items */ 490 mMainMenu = new QIMenu (this); 491 mDevicesCDMenu = new QMenu (this); 492 mDevicesFDMenu = new QMenu (this); 493 mDevicesNetworkMenu = new QMenu (this); 494 mDevicesSFMenu = new QMenu (this); 495 mDevicesUSBMenu = new VBoxUSBMenu (this); 496 497 /* Machine submenu */ 498 mVMMenu = menuBar()->addMenu (QString::null); 499 mMainMenu->addMenu (mVMMenu); 500 mVmDisMouseIntegrMenu = new VBoxSwitchMenu (mVMMenu, mVmDisableMouseIntegrAction, true); 501 #if 0 /* TODO: Allow to setup status-bar! */ 502 mVmAutoresizeMenu = new VBoxSwitchMenu (mVMMenu, mVmAutoresizeGuestAction); 503 #endif 504 505 mVMMenu->addAction (mVmFullscreenAction); 506 mVMMenu->addAction (mVmSeamlessAction); 507 mVMMenu->addAction (mVmAutoresizeGuestAction); 508 mVMMenu->addAction (mVmAdjustWindowAction); 509 mVMMenu->addSeparator(); 510 mVMMenu->addAction (mVmDisableMouseIntegrAction); 511 mVMMenu->addSeparator(); 512 mVMMenu->addAction (mVmTypeCADAction); 513 #ifdef Q_WS_X11 514 mVMMenu->addAction (mVmTypeCABSAction); 515 #endif 516 mVMMenu->addSeparator(); 517 mVMMenu->addAction (mVmTakeSnapshotAction); 518 mVMMenu->addSeparator(); 519 mVMMenu->addAction (mVmShowInformationDlgAction); 520 mVMMenu->addSeparator(); 521 mVMMenu->addAction (mVmResetAction); 522 mVMMenu->addAction (mVmPauseAction); 523 mVMMenu->addAction (mVmACPIShutdownAction); 524 #ifndef Q_WS_MAC 525 mVMMenu->addSeparator(); 526 #endif /* Q_WS_MAC */ 527 mVMMenu->addAction (mVmCloseAction); 528 529 /* Devices submenu */ 530 mDevicesMenu = menuBar()->addMenu (QString::null); 531 mMainMenu->addMenu (mDevicesMenu); 532 533 mDevicesCDMenu->setIcon (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png")); 534 mDevicesFDMenu->setIcon (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png")); 535 mDevicesUSBMenu->setIcon (VBoxGlobal::iconSet (":/usb_16px.png", ":/usb_disabled_16px.png")); 536 537 mDevicesMenu->addMenu (mDevicesCDMenu); 538 mDevicesMenu->addMenu (mDevicesFDMenu); 539 mDevicesMenu->addAction (mDevicesNetworkDialogAction); 540 mDevicesMenu->addAction (mDevicesSFDialogAction); 541 mDevicesMenu->addMenu (mDevicesUSBMenu); 542 543 #if 0 /* TODO: Allow to setup status-bar! */ 544 mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, mDevicesSwitchVrdpAction); 545 #endif 546 mDevicesSwitchVrdpSeparator = mDevicesMenu->addSeparator(); 547 mDevicesMenu->addAction (mDevicesSwitchVrdpAction); 548 549 mDevicesMenu->addSeparator(); 550 mDevicesMenu->addAction (mDevicesInstallGuestToolsAction); 551 552 #ifdef VBOX_WITH_DEBUGGER_GUI 553 /* Debug submenu */ 554 if (vboxGlobal().isDebuggerEnabled()) 555 { 556 mDbgMenu = menuBar()->addMenu (QString::null); 557 mMainMenu->addMenu (mDbgMenu); 558 mDbgMenu->addAction (mDbgStatisticsAction); 559 mDbgMenu->addAction (mDbgCommandLineAction); 560 mDbgMenu->addAction (mDbgLoggingAction); 561 } 562 else 563 mDbgMenu = 0; 564 #endif 565 566 /* Help submenu */ 567 mHelpMenu = menuBar()->addMenu (QString::null); 568 mMainMenu->addMenu (mHelpMenu); 569 mHelpActions.addTo (mHelpMenu); 570 571 /* Machine submenu for mini-toolbar */ 572 mVMMenuMini = new QMenu (this); 573 mVMMenuMini->addAction (mVmTypeCADAction); 574 #ifdef Q_WS_X11 575 mVMMenuMini->addAction (mVmTypeCABSAction); 576 #endif 577 mVMMenuMini->addSeparator(); 578 mVMMenuMini->addAction (mVmTakeSnapshotAction); 579 mVMMenuMini->addSeparator(); 580 mVMMenuMini->addAction (mVmShowInformationDlgAction); 581 mVMMenuMini->addSeparator(); 582 mVMMenuMini->addAction (mVmResetAction); 583 mVMMenuMini->addAction (mVmPauseAction); 584 mVMMenuMini->addAction (mVmACPIShutdownAction); 585 586 /* Status bar */ 587 QWidget *indicatorBox = new QWidget; 588 QHBoxLayout *indicatorBoxHLayout = new QHBoxLayout (indicatorBox); 589 VBoxGlobal::setLayoutMargin (indicatorBoxHLayout, 0); 590 indicatorBoxHLayout->setSpacing (5); 591 592 /* i/o devices */ 593 mHDLed = new QIStateIndicator (KDeviceActivity_Idle); 594 mHDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/hd_16px.png")); 595 mHDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/hd_read_16px.png")); 596 mHDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/hd_write_16px.png")); 597 mHDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/hd_disabled_16px.png")); 598 indicatorBoxHLayout->addWidget (mHDLed); 599 mCDLed = new QIStateIndicator (KDeviceActivity_Idle); 600 mCDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/cd_16px.png")); 601 mCDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/cd_read_16px.png")); 602 mCDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/cd_write_16px.png")); 603 mCDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/cd_disabled_16px.png")); 604 indicatorBoxHLayout->addWidget (mCDLed); 605 #if 0 /* TODO: Allow to setup status-bar! */ 606 mFDLed = new QIStateIndicator (KDeviceActivity_Idle); 607 mFDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/fd_16px.png")); 608 mFDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/fd_read_16px.png")); 609 mFDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/fd_write_16px.png")); 610 mFDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/fd_disabled_16px.png")); 611 indicatorBoxHLayout->addWidget (mFDLed); 612 #endif 613 mNetLed = new QIStateIndicator (KDeviceActivity_Idle); 614 mNetLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/nw_16px.png")); 615 mNetLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/nw_read_16px.png")); 616 mNetLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/nw_write_16px.png")); 617 mNetLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/nw_disabled_16px.png")); 618 indicatorBoxHLayout->addWidget (mNetLed); 619 mUSBLed = new QIStateIndicator (KDeviceActivity_Idle); 620 mUSBLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/usb_16px.png")); 621 mUSBLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/usb_read_16px.png")); 622 mUSBLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/usb_write_16px.png")); 623 mUSBLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/usb_disabled_16px.png")); 624 indicatorBoxHLayout->addWidget (mUSBLed); 625 mSFLed = new QIStateIndicator (KDeviceActivity_Idle); 626 mSFLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/shared_folder_16px.png")); 627 mSFLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/shared_folder_read_16px.png")); 628 mSFLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/shared_folder_write_16px.png")); 629 mSFLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/shared_folder_disabled_16px.png")); 630 indicatorBoxHLayout->addWidget (mSFLed); 631 632 /* virtualization */ 633 mVirtLed = new QIStateIndicator (0); 634 mVirtLed->setStateIcon (0, QPixmap (":/vtx_amdv_disabled_16px.png")); 635 mVirtLed->setStateIcon (1, QPixmap (":/vtx_amdv_16px.png")); 636 indicatorBoxHLayout->addWidget (mVirtLed); 637 638 QFrame *separator = new QFrame(); 639 separator->setFrameStyle (QFrame::VLine | QFrame::Sunken); 640 indicatorBoxHLayout->addWidget (separator); 641 642 /* mouse */ 643 mMouseLed = new QIStateIndicator (0); 644 mMouseLed->setStateIcon (0, QPixmap (":/mouse_disabled_16px.png")); 645 mMouseLed->setStateIcon (1, QPixmap (":/mouse_16px.png")); 646 mMouseLed->setStateIcon (2, QPixmap (":/mouse_seamless_16px.png")); 647 mMouseLed->setStateIcon (3, QPixmap (":/mouse_can_seamless_16px.png")); 648 mMouseLed->setStateIcon (4, QPixmap (":/mouse_can_seamless_uncaptured_16px.png")); 649 indicatorBoxHLayout->addWidget (mMouseLed); 650 651 /* host key */ 652 mHostkeyLedContainer = new QWidget; 653 QHBoxLayout *hostkeyLEDContainerLayout = new QHBoxLayout (mHostkeyLedContainer); 654 VBoxGlobal::setLayoutMargin (hostkeyLEDContainerLayout, 0); 655 hostkeyLEDContainerLayout->setSpacing (3); 656 indicatorBoxHLayout->addWidget (mHostkeyLedContainer); 657 658 mHostkeyLed = new QIStateIndicator (0); 659 mHostkeyLed->setStateIcon (0, QPixmap (":/hostkey_16px.png")); 660 mHostkeyLed->setStateIcon (1, QPixmap (":/hostkey_captured_16px.png")); 661 mHostkeyLed->setStateIcon (2, QPixmap (":/hostkey_pressed_16px.png")); 662 mHostkeyLed->setStateIcon (3, QPixmap (":/hostkey_captured_pressed_16px.png")); 663 hostkeyLEDContainerLayout->addWidget (mHostkeyLed); 664 mHostkeyName = new QLabel (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 665 hostkeyLEDContainerLayout->addWidget (mHostkeyName); 666 667 #if 0 /* TODO: Allow to setup status-bar! */ 668 /* VRDP Led */ 669 mVrdpLed = new QIStateIndicator (0, indicatorBox, "mVrdpLed", Qt::WNoAutoErase); 670 mVrdpLed->setStateIcon (0, QPixmap (":/vrdp_disabled_16px.png")); 671 mVrdpLed->setStateIcon (1, QPixmap (":/vrdp_16px.png")); 672 /* Auto-Resize LED */ 673 mAutoresizeLed = new QIStateIndicator (1, indicatorBox, "mAutoresizeLed", Qt::WNoAutoErase); 674 mAutoresizeLed->setStateIcon (0, QPixmap (":/auto_resize_off_disabled_16px.png")); 675 mAutoresizeLed->setStateIcon (1, QPixmap (":/auto_resize_off_16px.png")); 676 mAutoresizeLed->setStateIcon (2, QPixmap (":/auto_resize_on_disabled_16px.png")); 677 mAutoresizeLed->setStateIcon (3, QPixmap (":/auto_resize_on_16px.png")); 678 #endif 679 680 /* add to statusbar */ 681 statusBar()->addPermanentWidget (indicatorBox, 0); 682 683 /* Retranslate UI */ 684 retranslateUi(); 685 686 setWindowTitle (mCaptionPrefix); 687 688 /* Connections */ 689 connect (mVmFullscreenAction, SIGNAL (toggled (bool)), this, SLOT (vmFullscreen (bool))); 690 connect (mVmSeamlessAction, SIGNAL (toggled (bool)), this, SLOT (vmSeamless (bool))); 691 connect (mVmAutoresizeGuestAction, SIGNAL (toggled (bool)), this, SLOT (vmAutoresizeGuest (bool))); 692 connect (mVmAdjustWindowAction, SIGNAL (triggered()), this, SLOT (vmAdjustWindow())); 693 connect (mVmDisableMouseIntegrAction, SIGNAL (toggled (bool)), this, SLOT (vmDisableMouseIntegration (bool))); 694 connect (mVmTypeCADAction, SIGNAL (triggered()), this, SLOT (vmTypeCAD())); 695 #ifdef Q_WS_X11 696 connect (mVmTypeCABSAction, SIGNAL (triggered()), this, SLOT (vmTypeCABS())); 697 #endif 698 connect (mVmTakeSnapshotAction, SIGNAL (triggered()), this, SLOT (vmTakeSnapshot())); 699 connect (mVmShowInformationDlgAction, SIGNAL (triggered()), this, SLOT (vmShowInfoDialog())); 700 connect (mVmResetAction, SIGNAL (triggered()), this, SLOT (vmReset())); 701 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 702 connect (mVmACPIShutdownAction, SIGNAL (triggered()), this, SLOT (vmACPIShutdown())); 703 connect (mVmCloseAction, SIGNAL (triggered()), this, SLOT (vmClose())); 704 705 connect (mDevicesCDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 706 connect (mDevicesFDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 707 connect (mDevicesNetworkMenu, SIGNAL (aboutToShow()), this, SLOT (prepareNetworkMenu())); 708 connect (mDevicesSFMenu, SIGNAL (aboutToShow()), this, SLOT (prepareSFMenu())); 709 connect (mDevicesUSBMenu, SIGNAL(triggered (QAction *)), this, SLOT(switchUSB (QAction *))); 710 711 connect (mDevicesNetworkDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenNetworkDialog())); 712 connect (mDevicesSFDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenSFDialog())); 713 connect (mDevicesSwitchVrdpAction, SIGNAL (toggled (bool)), this, SLOT (devicesSwitchVrdp (bool))); 714 connect (mDevicesInstallGuestToolsAction, SIGNAL (triggered()), this, SLOT (devicesInstallGuestAdditions())); 715 716 connect (mCDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 717 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 718 #if 0 /* TODO: Allow to setup status-bar! */ 719 connect (mFDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 720 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 721 #endif 722 connect (mNetLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 723 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 724 connect (mUSBLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 725 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 726 connect (mSFLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 727 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 728 connect (mMouseLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 729 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 730 #if 0 /* TODO: Allow to setup status-bar! */ 731 connect (mVrdpLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 732 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 733 connect (mAutoresizeLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 734 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 735 #endif 736 737 /* Watch global settings changes */ 738 connect (&vboxGlobal().settings(), SIGNAL (propertyChanged (const char *, const char *)), 739 this, SLOT (processGlobalSettingChange (const char *, const char *))); 740 #ifdef Q_WS_MAC 741 connect (&vboxGlobal(), SIGNAL (dockIconUpdateChanged (const VBoxChangeDockIconUpdateEvent &)), 742 this, SLOT (changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &))); 743 connect (&vboxGlobal(), SIGNAL (presentationModeChanged (const VBoxChangePresentationModeEvent &)), 744 this, SLOT (changePresentationMode (const VBoxChangePresentationModeEvent &))); 745 #endif 746 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 if (mDbgMenu) 749 connect (mDbgMenu, SIGNAL (aboutToShow()), this, SLOT (dbgPrepareDebugMenu())); 750 if (mDbgStatisticsAction) 751 connect (mDbgStatisticsAction, SIGNAL (triggered()), this, SLOT (dbgShowStatistics())); 752 if (mDbgCommandLineAction) 753 connect (mDbgCommandLineAction, SIGNAL (triggered()), this, SLOT (dbgShowCommandLine())); 754 if (mDbgLoggingAction) 755 connect (mDbgLoggingAction, SIGNAL (toggled (bool)), this, SLOT (dbgLoggingToggled (bool))); 756 #endif 757 758 #ifdef Q_WS_MAC 759 /* For the status bar on Cocoa */ 760 setUnifiedTitleAndToolBarOnMac (true); 761 # ifdef VBOX_WITH_ICHAT_THEATER 762 // int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 }; 763 // HIWindowChangeAttributes (window, setAttr, 0); 764 initSharedAVManager(); 765 # endif 766 #endif 767 768 mMaskShift.scale (0, 0, Qt::IgnoreAspectRatio); 769 } 770 771 VBoxConsoleWnd::~VBoxConsoleWnd() 772 { 773 closeView(); 774 775 #ifdef VBOX_WITH_DEBUGGER_GUI 776 dbgDestroy(); 777 #endif 778 } 779 780 /** 781 * Opens a new console view to interact with a given VM. 782 * Does nothing if the console view is already opened. 783 * Used by VBoxGlobal::startMachine(), should not be called directly. 784 */ 785 bool VBoxConsoleWnd::openView (const CSession &aSession) 786 { 787 LogFlowFuncEnter(); 788 789 if (mConsole) 790 { 791 LogFlowFunc (("Already opened\n")); 792 LogFlowFuncLeave(); 793 return false; 794 } 795 796 #ifdef Q_WS_MAC 797 /* We have to make sure that we are getting the front most process. This is 798 * necessary for Qt versions > 4.3.3 */ 799 ProcessSerialNumber psn = { 0, kCurrentProcess }; 800 ::SetFrontProcess (&psn); 801 #endif /* Q_WS_MAC */ 802 803 mSession = aSession; 804 805 if (!centralWidget()) 806 { 807 setCentralWidget (new QWidget (this)); 808 QGridLayout *pMainLayout = new QGridLayout (centralWidget()); 809 VBoxGlobal::setLayoutMargin (pMainLayout, 0); 810 pMainLayout->setSpacing (0); 811 812 mShiftingSpacerLeft = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 813 mShiftingSpacerTop = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 814 mShiftingSpacerRight = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 815 mShiftingSpacerBottom = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 816 pMainLayout->addItem (mShiftingSpacerTop, 0, 0, 1, -1); 817 pMainLayout->addItem (mShiftingSpacerLeft, 1, 0); 818 pMainLayout->addItem (mShiftingSpacerRight, 1, 2); 819 pMainLayout->addItem (mShiftingSpacerBottom, 2, 0, 1, -1); 820 } 821 822 mVmPauseAction->setChecked (false); 823 824 CConsole console = mSession.GetConsole(); 825 AssertWrapperOk (mSession); 826 827 CMachine machine = mSession.GetMachine(); 828 829 #ifdef VBOX_WITH_VIDEOHWACCEL 830 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled */ 831 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() 832 && VBoxGlobal::isAcceleration2DVideoAvailable() 833 ; 834 #endif 835 836 mConsole = new VBoxConsoleView (this, console, vboxGlobal().vmRenderMode(), 837 #ifdef VBOX_WITH_VIDEOHWACCEL 838 bAccelerate2DVideo, 839 #endif 840 centralWidget()); 841 qobject_cast <QGridLayout*> (centralWidget()->layout())->addWidget (mConsole, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 842 843 /* Mini toolbar */ 844 bool isActive = !(machine.GetExtraData (VBoxDefs::GUI_ShowMiniToolBar) == "no"); 845 bool isAtTop = (machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAlignment) == "top"); 846 bool isAutoHide = !(machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide) == "off"); 847 QList <QMenu*> menus (QList <QMenu*>() << mVMMenuMini << mDevicesMenu); 848 mMiniToolBar = new VBoxMiniToolBar (centralWidget(), isAtTop ? VBoxMiniToolBar::AlignTop : VBoxMiniToolBar::AlignBottom, 849 isActive, isAutoHide); 850 *mMiniToolBar << menus; 851 connect (mMiniToolBar, SIGNAL (exitAction()), this, SLOT (mtExitMode())); 852 connect (mMiniToolBar, SIGNAL (closeAction()), this, SLOT (mtCloseVM())); 853 connect (mMiniToolBar, SIGNAL (geometryUpdated()), this, SLOT (mtMaskUpdate())); 854 connect (this, SIGNAL (closing()), mMiniToolBar, SLOT (close())); 855 856 activateUICustomizations(); 857 858 /* Set the VM-specific application icon */ 859 /* Not on Mac OS X. The dock icon is handled below. */ 860 #ifndef Q_WS_MAC 861 setWindowIcon (vboxGlobal().vmGuestOSTypeIcon (machine.GetOSTypeId())); 862 #endif 863 864 /* Restore the position of the window and some options */ 865 { 866 QString str = machine.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 867 868 bool ok = false, max = false; 869 int x = 0, y = 0, w = 0, h = 0; 870 x = str.section (',', 0, 0).toInt (&ok); 871 if (ok) 872 y = str.section (',', 1, 1).toInt (&ok); 873 if (ok) 874 w = str.section (',', 2, 2).toInt (&ok); 875 if (ok) 876 h = str.section (',', 3, 3).toInt (&ok); 877 if (ok) 878 max = str.section (',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 879 880 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 881 QApplication::desktop()->availableGeometry (this); 882 883 if (ok /* previous parameters were read correctly */) 884 { 885 mNormalGeo = QRect (x, y, w, h); 886 setGeometry (mNormalGeo); 887 888 /* Normalize to the optimal size */ 889 mConsole->normalizeGeometry (true /* adjustPosition */); 890 891 if (max) 892 { 893 /* Maximize if needed */ 894 setWindowState (windowState() | Qt::WindowMaximized); 895 mWasMax = max; 896 } 897 } 898 else 899 { 900 /* Normalize to the optimal size */ 901 mConsole->normalizeGeometry (true /* adjustPosition */); 902 903 /* Move newly created window to the screen center. */ 904 mNormalGeo = geometry(); 905 mNormalGeo.moveCenter (ar.center()); 906 setGeometry (mNormalGeo); 907 } 908 909 show(); 910 911 /* Process show & possible maximize events */ 912 qApp->processEvents(); 913 914 mVmSeamlessAction->setEnabled (false); 915 str = machine.GetExtraData (VBoxDefs::GUI_Seamless); 916 if (str == "on") 917 mVmSeamlessAction->setChecked (true); 918 919 str = machine.GetExtraData (VBoxDefs::GUI_AutoresizeGuest); 920 if (str != "off") 921 mVmAutoresizeGuestAction->setChecked (true); 922 923 str = machine.GetExtraData (VBoxDefs::GUI_FirstRun); 924 if (str == "yes") 925 mIsFirstTimeStarted = true; 926 else if (!str.isEmpty()) 927 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 928 929 str = machine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime); 930 if (str == "no") 931 mIsAutoSaveMedia = false; 932 933 /* Check if one of extended modes to be activated on loading */ 934 QString fsMode = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 935 QString slMode = machine.GetExtraData (VBoxDefs::GUI_Seamless); 936 bool extendedMode = fsMode == "on" || slMode == "on"; 937 938 /* If one of extended modes to be loaded we have to ignore default 939 * console resize event which will come from VGA Device on loading. */ 940 if (extendedMode) 941 mConsole->requestToResize (QSize (w, h - menuBar()->height() - statusBar()->height())); 942 } 943 944 /* initialize storage stuff */ 945 int cdDevicesCount = 0; 946 int fdDevicesCount = 0; 947 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 948 foreach (const CMediumAttachment &attachment, attachments) 949 { 950 if (attachment.GetType() == KDeviceType_DVD) 951 ++ cdDevicesCount; 952 if (attachment.GetType() == KDeviceType_Floppy) 953 ++ fdDevicesCount; 954 } 955 mDevicesCDMenu->menuAction()->setData (cdDevicesCount); 956 mDevicesFDMenu->menuAction()->setData (fdDevicesCount); 957 mDevicesCDMenu->menuAction()->setVisible (cdDevicesCount); 958 mDevicesFDMenu->menuAction()->setVisible (fdDevicesCount); 959 960 /* initialize usb stuff */ 961 CUSBController usbctl = machine.GetUSBController(); 962 if (usbctl.isNull()) 963 { 964 /* hide usb_menu & usb_separator & usb_status_led */ 965 mDevicesUSBMenu->setVisible (false); 966 mUSBLed->setHidden (true); 967 } 968 else 969 { 970 bool isUSBEnabled = usbctl.GetEnabled(); 971 mDevicesUSBMenu->setEnabled (isUSBEnabled); 972 mDevicesUSBMenu->setConsole (console); 973 mUSBLed->setState (isUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null); 974 } 975 976 /* initialize vrdp stuff */ 977 CVRDPServer vrdpsrv = machine.GetVRDPServer(); 978 if (vrdpsrv.isNull()) 979 { 980 /* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */ 981 mDevicesSwitchVrdpAction->setVisible (false); 982 mDevicesSwitchVrdpSeparator->setVisible (false); 983 #if 0 /* TODO: Allow to setup status-bar! */ 984 mVrdpLed->setHidden (true); 985 #endif 986 } 987 988 /* start an idle timer that will update device lighths */ 989 connect (mIdleTimer, SIGNAL (timeout()), SLOT (updateDeviceLights())); 990 mIdleTimer->start (50); 991 992 connect (mConsole, SIGNAL (mouseStateChanged (int)), this, SLOT (updateMouseState (int))); 993 connect (mConsole, SIGNAL (keyboardStateChanged (int)), mHostkeyLed, SLOT (setState (int))); 994 connect (mConsole, SIGNAL (machineStateChanged (KMachineState)), this, SLOT (updateMachineState (KMachineState))); 995 connect (mConsole, SIGNAL (additionsStateChanged (const QString&, bool, bool, bool)), 996 this, SLOT (updateAdditionsState (const QString &, bool, bool, bool))); 997 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), 998 this, SLOT (updateMediaDriveState (VBoxDefs::MediumType))); 999 connect (mConsole, SIGNAL (usbStateChange()), this, SLOT (updateUsbState())); 1000 connect (mConsole, SIGNAL (networkStateChange()), this, SLOT (updateNetworkAdaptersState())); 1001 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateSharedFoldersState())); 1002 1003 #ifdef Q_WS_MAC 1004 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 1005 /* Default to true if it is an empty value */ 1006 bool f = (testStr.isEmpty() || testStr == "true"); 1007 mConsole->setDockIconEnabled (f); 1008 mConsole->updateDockOverlay(); 1009 #endif 1010 1011 /* set the correct initial mMachineState value */ 1012 mMachineState = console.GetState(); 1013 1014 mConsole->normalizeGeometry (false /* adjustPosition */); 1015 1016 updateAppearanceOf (AllStuff); 1017 1018 if (vboxGlobal().settings().autoCapture()) 1019 vboxProblem().remindAboutAutoCapture(); 1020 1021 /* 1022 * The further startup procedure should be done after we leave this method 1023 * and enter the main event loop in main(), because it may result into 1024 * showing various modal dialogs that will process events from within 1025 * this method that in turn can lead to various side effects like this 1026 * window is closed before this method returns, etc. 1027 */ 1028 1029 QTimer::singleShot (0, this, SLOT (finalizeOpenView())); 1030 1031 LogFlowFuncLeave(); 1032 return true; 1033 } 1034 1035 void VBoxConsoleWnd::setMouseIntegrationLocked (bool aDisabled) 1036 { 1037 mVmDisableMouseIntegrAction->setChecked (false); 1038 mVmDisableMouseIntegrAction->setEnabled (aDisabled); 1039 } 1040 1041 /** 1042 * Shows up and activates the popup version of the main menu. 1043 * 1044 * @param aCenter If @a true, center the popup menu on the screen, otherwise 1045 * show it at the current mouse pointer location. 1046 */ 1047 void VBoxConsoleWnd::popupMainMenu (bool aCenter) 1048 { 1049 QPoint pos = QCursor::pos(); 1050 if (aCenter) 1051 { 1052 QRect deskGeo = QApplication::desktop()->screenGeometry (this); 1053 QRect popGeo = mMainMenu->frameGeometry(); 1054 popGeo.moveCenter (QPoint (deskGeo.width() / 2, deskGeo.height() / 2)); 1055 pos = popGeo.topLeft(); 1056 } 1057 else 1058 { 1059 /* put the menu's bottom right corner to the pointer's hotspot point */ 1060 pos.setX (pos.x() - mMainMenu->frameGeometry().width()); 1061 pos.setY (pos.y() - mMainMenu->frameGeometry().height()); 1062 } 1063 1064 mMainMenu->popup (pos); 1065 mMainMenu->selectFirstAction(); 1066 #ifdef Q_WS_WIN 1067 mMainMenu->activateWindow(); 1068 #endif 1069 } 1070 1071 void VBoxConsoleWnd::installGuestAdditionsFrom (const QString &aSource) 1072 { 1073 CVirtualBox vbox = vboxGlobal().virtualBox(); 1074 QString uuid; 1075 1076 CMedium image = vbox.FindDVDImage (aSource); 1077 if (image.isNull()) 1078 { 1079 image = vbox.OpenDVDImage (aSource, uuid); 1080 if (vbox.isOk()) 1081 uuid = image.GetId(); 1082 } 1083 else 1084 uuid = image.GetId(); 1085 1086 if (!vbox.isOk()) 1087 return vboxProblem().cannotOpenMedium (this, vbox, VBoxDefs::MediumType_DVD, aSource); 1088 1089 Assert (!uuid.isNull()); 1090 CMachine m = mSession.GetMachine(); 1091 1092 QString ctrName; 1093 LONG ctrPort = -1, ctrDevice = -1; 1094 /* Searching for the first suitable slot */ 1095 { 1096 CStorageControllerVector controllers = m.GetStorageControllers(); 1097 int i = 0; 1098 while (i < controllers.size() && ctrName.isNull()) 1099 { 1100 CStorageController controller = controllers [i]; 1101 CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController (controller.GetName()); 1102 int j = 0; 1103 while (j < attachments.size() && ctrName.isNull()) 1104 { 1105 CMediumAttachment attachment = attachments [j]; 1106 if (attachment.GetType() == KDeviceType_DVD) 1107 { 1108 ctrName = controller.GetName(); 1109 ctrPort = attachment.GetPort(); 1110 ctrDevice = attachment.GetDevice(); 1111 } 1112 ++ j; 1113 } 1114 ++ i; 1115 } 1116 } 1117 1118 if (!ctrName.isNull()) 1119 { 1120 bool isMounted = false; 1121 1122 /* Mount medium to the predefined port/device */ 1123 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, false /* force */); 1124 if (m.isOk()) 1125 isMounted = true; 1126 else 1127 { 1128 /* Ask for force mounting */ 1129 if (vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 1130 { 1131 /* Force mount medium to the predefined port/device */ 1132 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, true /* force */); 1133 if (m.isOk()) 1134 isMounted = true; 1135 else 1136 vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, false /* retry? */); 1137 } 1138 } 1139 1140 /* Save medium mounted at runtime */ 1141 if (isMounted && mIsAutoSaveMedia) 1142 { 1143 m.SaveSettings(); 1144 if (!m.isOk()) 1145 vboxProblem().cannotSaveMachineSettings (m); 1146 } 1147 } 1148 else 1149 vboxProblem().cannotMountGuestAdditions (m.GetName()); 1150 } 1151 1152 void VBoxConsoleWnd::setMask (const QRegion &aRegion) 1153 { 1154 QRegion region = aRegion; 1155 1156 /* The global mask shift cause of toolbars and such things. */ 1157 region.translate (mMaskShift.width(), mMaskShift.height()); 1158 1159 /* Including mini toolbar area */ 1160 QRegion toolBarRegion (mMiniToolBar->mask()); 1161 toolBarRegion.translate (mMiniToolBar->mapToGlobal (toolBarRegion.boundingRect().topLeft()) - QPoint (1, 0)); 1162 region += toolBarRegion; 1163 1164 /* Restrict the drawing to the available space on the screen. 1165 * (The &operator is better than the previous used -operator, 1166 * because this excludes space around the real screen also. 1167 * This is necessary for the mac.) */ 1168 region &= mStrictedRegion; 1169 1170 #ifdef Q_WS_WIN 1171 QRegion difference = mPrevRegion.subtract (region); 1172 1173 /* Region offset calculation */ 1174 int fleft = 0, ftop = 0; 1175 1176 /* Visible region calculation */ 1177 HRGN newReg = CreateRectRgn (0, 0, 0, 0); 1178 CombineRgn (newReg, region.handle(), 0, RGN_COPY); 1179 OffsetRgn (newReg, fleft, ftop); 1180 1181 /* Invisible region calculation */ 1182 HRGN diffReg = CreateRectRgn (0, 0, 0, 0); 1183 CombineRgn (diffReg, difference.handle(), 0, RGN_COPY); 1184 OffsetRgn (diffReg, fleft, ftop); 1185 1186 /* Set the current visible region and clean the previous */ 1187 SetWindowRgn (winId(), newReg, FALSE); 1188 RedrawWindow (0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 1189 RedrawWindow (mConsole->viewport()->winId(), 0, 0, RDW_INVALIDATE); 1190 1191 mPrevRegion = region; 1192 #elif defined (Q_WS_MAC) 1193 # if defined (VBOX_GUI_USE_QUARTZ2D) 1194 if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) 1195 { 1196 /* If we are using the Quartz2D backend we have to trigger 1197 * an repaint only. All the magic clipping stuff is done 1198 * in the paint engine. */ 1199 ::darwinWindowInvalidateShape (mConsole->viewport()); 1200 } 1201 else 1202 # endif 1203 { 1204 /* This is necessary to avoid the flicker by an mask update. 1205 * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html 1206 * for the hint. 1207 * There *must* be a better solution. */ 1208 if (!region.isEmpty()) 1209 region |= QRect (0, 0, 1, 1); 1210 // /* Save the current region for later processing in the darwin event handler. */ 1211 // mCurrRegion = region; 1212 // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately 1213 // * this command flushes a copy of the backbuffer to the screen after the new 1214 // * mask is set. This leads into a missplaced drawing of the content. Currently 1215 // * no alternative to this and also this is not 100% perfect. */ 1216 // repaint(); 1217 // qApp->processEvents(); 1218 // /* Now force the reshaping of the window. This is definitly necessary. */ 1219 // ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId())); 1220 QMainWindow::setMask (region); 1221 // HIWindowInvalidateShadow (::darwinToWindowRef (mConsole->viewport())); 1222 } 1223 #else 1224 QMainWindow::setMask (region); 1225 #endif 1226 } 1227 1228 void VBoxConsoleWnd::clearMask() 1229 { 1230 #ifdef Q_WS_WIN 1231 SetWindowRgn (winId(), 0, TRUE); 1232 #else 1233 QMainWindow::clearMask(); 1234 #endif 1235 } 1236 1237 void VBoxConsoleWnd::onDisplayResize (ulong aHeight, ulong aWidth) 1238 { 1239 if (mIsSeamless && QApplication::desktop()->availableGeometry (this).size() != QSize (aHeight, aWidth)) 1240 { 1241 mVmSeamlessAction->setChecked (false); 1242 /* should be cleared already, but just in case */ 1243 if (mIsSeamless) 1244 toggleFullscreenMode (false, true); 1245 } 1246 } 1247 1248 1249 bool VBoxConsoleWnd::event (QEvent *aEvent) 1250 { 1251 switch (aEvent->type()) 1252 { 1253 /* By handling every Resize and Move we keep track of the normal 1254 * (non-minimized and non-maximized) window geometry. Shame on Qt 1255 * that it doesn't provide this geometry in its public APIs. */ 1256 1257 case QEvent::Resize: 1258 { 1259 QResizeEvent *re = (QResizeEvent *) aEvent; 1260 1261 if (!mIsWaitingModeResize && !isWindowMaximized() && 1262 !isTrueFullscreen() && !isTrueSeamless()) 1263 { 1264 mNormalGeo.setSize (re->size()); 1265 #ifdef VBOX_WITH_DEBUGGER_GUI 1266 dbgAdjustRelativePos(); 1267 #endif 1268 } 1269 1270 if (mIsWaitingModeResize) 1271 { 1272 if (!mIsFullscreen && !mIsSeamless) 1273 { 1274 mIsWaitingModeResize = false; 1275 QTimer::singleShot (0, this, SLOT (onExitFullscreen())); 1276 } 1277 } 1278 break; 1279 } 1280 case QEvent::Move: 1281 { 1282 if (!isWindowMaximized() && !isTrueFullscreen() && !isTrueSeamless()) 1283 { 1284 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1285 #ifdef VBOX_WITH_DEBUGGER_GUI 1286 dbgAdjustRelativePos(); 1287 #endif 1288 } 1289 break; 1290 } 1291 #ifdef Q_WS_MAC 1292 case QEvent::Paint: 1293 { 1294 if (mIsSeamless) 1295 { 1296 /* Clear the background */ 1297 CGContextClearRect (::darwinToCGContextRef (this), ::darwinToCGRect (frameGeometry())); 1298 } 1299 break; 1300 } 1301 #endif 1302 case StatusTipEvent::Type: 1303 { 1304 StatusTipEvent *ev = (StatusTipEvent*) aEvent; 1305 statusBar()->showMessage (ev->mTip); 187 m_pVisualState = new UIVisualStateSeamless(this, m_session, m_pActionsPool); 1306 188 break; 1307 189 } … … 1309 191 break; 1310 192 } 1311 1312 return QMainWindow::event (aEvent);1313 193 } 1314 194 1315 void VBoxConsoleWnd::closeEvent (QCloseEvent *aEvent) 1316 { 1317 LogFlowFuncEnter(); 1318 1319 static const char *kSave = "save"; 1320 static const char *kShutdown = "shutdown"; 1321 static const char *kPowerOff = "powerOff"; 1322 static const char *kDiscardCurState = "discardCurState"; 1323 1324 if (!mConsole) 1325 { 1326 aEvent->accept(); 1327 LogFlowFunc (("Console already destroyed!")); 1328 LogFlowFuncLeave(); 1329 return; 1330 } 1331 1332 switch (mMachineState) 1333 { 1334 case KMachineState_PoweredOff: 1335 case KMachineState_Saved: 1336 case KMachineState_Teleported: 1337 case KMachineState_Aborted: 1338 /* The machine has been already powered off or saved or aborted -- close the window immediately. */ 1339 aEvent->accept(); 1340 break; 1341 1342 default: 1343 /* The machine is in some temporary state like Saving or Stopping. 1344 * Ignore the close event. When it is Stopping, it will be soon closed anyway from updateMachineState(). 1345 * In all other cases, an appropriate progress dialog will be shown within a few seconds. */ 1346 aEvent->ignore(); 1347 break; 1348 1349 case KMachineState_Teleporting: /** @todo Live Migration: Test closing a VM that's being teleported or snapshotted. */ 1350 case KMachineState_LiveSnapshotting: 1351 case KMachineState_Running: 1352 case KMachineState_Paused: 1353 case KMachineState_TeleportingPausedVM: /** @todo Live Migration: Check out this. */ 1354 case KMachineState_Stuck: 1355 /* Start with ignoring the close event */ 1356 aEvent->ignore(); 1357 1358 bool isACPIEnabled = mSession.GetConsole().GetGuestEnteredACPIMode(); 1359 1360 bool success = true; 1361 1362 bool wasPaused = mMachineState == KMachineState_Paused 1363 || mMachineState == KMachineState_Stuck 1364 || mMachineState == KMachineState_TeleportingPausedVM; 1365 if (!wasPaused) 1366 { 1367 /* Suspend the VM and ignore the close event if failed to do so. 1368 * pause() will show the error message to the user. */ 1369 success = mConsole->pause (true); 1370 } 1371 1372 if (success) 1373 { 1374 success = false; 1375 1376 CMachine machine = mSession.GetMachine(); 1377 VBoxCloseVMDlg dlg (this); 1378 QString typeId = machine.GetOSTypeId(); 1379 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 1380 1381 /* Make the Discard checkbox invisible if there are no snapshots */ 1382 dlg.mCbDiscardCurState->setVisible (machine.GetSnapshotCount() > 0); 1383 if (!machine.GetCurrentSnapshot().isNull()) 1384 dlg.mCbDiscardCurState->setText (dlg.mCbDiscardCurState->text().arg (machine.GetCurrentSnapshot().GetName())); 1385 1386 if (mMachineState != KMachineState_Stuck) 1387 { 1388 /* Read the last user's choice for the given VM */ 1389 QStringList lastAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1390 AssertWrapperOk (machine); 1391 if (lastAction [0] == kSave) 1392 { 1393 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1394 dlg.mRbSave->setChecked (true); 1395 dlg.mRbSave->setFocus(); 1396 } 1397 else if (lastAction [0] == kPowerOff || !isACPIEnabled) 1398 { 1399 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1400 dlg.mRbPowerOff->setChecked (true); 1401 dlg.mRbPowerOff->setFocus(); 1402 } 1403 else /* The default is ACPI Shutdown */ 1404 { 1405 dlg.mRbShutdown->setChecked (true); 1406 dlg.mRbShutdown->setFocus(); 1407 } 1408 dlg.mCbDiscardCurState->setChecked (lastAction.count() > 1 && lastAction [1] == kDiscardCurState); 1409 } 1410 else 1411 { 1412 /* The stuck VM can only be powered off; disable anything else and choose PowerOff */ 1413 dlg.mRbSave->setEnabled (false); 1414 dlg.mRbShutdown->setEnabled (false); 1415 dlg.mRbPowerOff->setChecked (true); 1416 } 1417 1418 bool wasShutdown = false; 1419 1420 if (dlg.exec() == QDialog::Accepted) 1421 { 1422 /* Disable auto closure because we want to have a chance to show 1423 * the error dialog on save state / power off failure. */ 1424 mNoAutoClose = true; 1425 1426 CConsole console = mConsole->console(); 1427 1428 if (dlg.mRbSave->isChecked()) 1429 { 1430 CProgress progress = console.SaveState(); 1431 1432 if (console.isOk()) 1433 { 1434 /* Show the "VM saving" progress dialog */ 1435 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1436 if (progress.GetResultCode() != 0) 1437 vboxProblem().cannotSaveMachineState (progress); 1438 else 1439 success = true; 1440 } 1441 else 1442 vboxProblem().cannotSaveMachineState (console); 1443 } 1444 else if (dlg.mRbShutdown->isChecked()) 1445 { 1446 /* Unpause the VM to let it grab the ACPI shutdown event */ 1447 mConsole->pause (false); 1448 /* Prevent the subsequent unpause request */ 1449 wasPaused = true; 1450 /* Signal ACPI shutdown (if there is no ACPI device, the 1451 * operation will fail) */ 1452 console.PowerButton(); 1453 wasShutdown = console.isOk(); 1454 if (!wasShutdown) 1455 vboxProblem().cannotACPIShutdownMachine (console); 1456 /* Success is always false because we never accept the close 1457 * window action when doing ACPI shutdown */ 1458 success = false; 1459 } 1460 else if (dlg.mRbPowerOff->isChecked()) 1461 { 1462 CProgress progress = console.PowerDown(); 1463 1464 if (console.isOk()) 1465 { 1466 /* Show the power down progress dialog */ 1467 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1468 if (progress.GetResultCode() != 0) 1469 vboxProblem().cannotStopMachine (progress); 1470 else 1471 success = true; 1472 } 1473 else 1474 vboxProblem().cannotStopMachine (console); 1475 1476 if (success) 1477 { 1478 /* Note: leave success = true even if we fail to 1479 * discard the current state later -- the console window 1480 * will closed anyway */ 1481 1482 /* Discard the current state if requested */ 1483 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo (&dlg)) 1484 { 1485 CSnapshot snapshot = machine.GetCurrentSnapshot(); 1486 CProgress progress = console.RestoreSnapshot (snapshot); 1487 if (console.isOk()) 1488 { 1489 /* Show the progress dialog */ 1490 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1491 if (progress.GetResultCode() != 0) 1492 vboxProblem().cannotRestoreSnapshot (progress, snapshot.GetName()); 1493 } 1494 else 1495 vboxProblem().cannotRestoreSnapshot (console, snapshot.GetName()); 1496 } 1497 } 1498 } 1499 1500 if (success) 1501 { 1502 /* Accept the close action on success */ 1503 aEvent->accept(); 1504 } 1505 1506 if (success || wasShutdown) 1507 { 1508 /* Read the last user's choice for the given VM */ 1509 QStringList prevAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1510 /* Memorize the last user's choice for the given VM */ 1511 QString lastAction = kPowerOff; 1512 if (dlg.mRbSave->isChecked()) 1513 lastAction = kSave; 1514 else if (dlg.mRbShutdown->isChecked() || 1515 (dlg.mRbPowerOff->isChecked() && prevAction [0] == kShutdown && !isACPIEnabled)) 1516 lastAction = kShutdown; 1517 else if (dlg.mRbPowerOff->isChecked()) 1518 lastAction = kPowerOff; 1519 else 1520 AssertFailed(); 1521 if (dlg.mCbDiscardCurState->isChecked()) 1522 (lastAction += ",") += kDiscardCurState; 1523 machine.SetExtraData (VBoxDefs::GUI_LastCloseAction, lastAction); 1524 AssertWrapperOk (machine); 1525 } 1526 } 1527 } 1528 1529 mNoAutoClose = false; 1530 1531 if ( mMachineState == KMachineState_PoweredOff 1532 || mMachineState == KMachineState_Saved 1533 || mMachineState == KMachineState_Teleported 1534 || mMachineState == KMachineState_Aborted 1535 ) 1536 { 1537 /* The machine has been stopped while showing the Close or the Pause 1538 * failure dialog -- accept the close event immediately. */ 1539 aEvent->accept(); 1540 } 1541 else 1542 { 1543 if (!success) 1544 { 1545 /* Restore the running state if needed */ 1546 if (!wasPaused && mMachineState == KMachineState_Paused) 1547 mConsole->pause (false); 1548 } 1549 } 1550 break; 1551 } 1552 1553 if (aEvent->isAccepted()) 1554 { 1555 #ifndef VBOX_GUI_SEPARATE_VM_PROCESS 1556 vboxGlobal().selectorWnd().show(); 1557 #endif 1558 1559 /* Stop LED update timer */ 1560 mIdleTimer->stop(); 1561 mIdleTimer->disconnect (SIGNAL (timeout()), this, SLOT (updateDeviceLights())); 1562 1563 /* Hide console window */ 1564 hide(); 1565 1566 /* Save the position of the window and some options */ 1567 CMachine machine = mSession.GetMachine(); 1568 QString winPos = QString ("%1,%2,%3,%4") 1569 .arg (mNormalGeo.x()).arg (mNormalGeo.y()) 1570 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 1571 if (isWindowMaximized() || (mIsFullscreen && mWasMax) || (mIsSeamless && mWasMax)) 1572 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowPosition_Max); 1573 1574 machine.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 1575 1576 machine.SetExtraData (VBoxDefs::GUI_Fullscreen, 1577 mVmFullscreenAction->isChecked() ? "on" : "off"); 1578 machine.SetExtraData (VBoxDefs::GUI_Seamless, 1579 mVmSeamlessAction->isChecked() ? "on" : "off"); 1580 machine.SetExtraData (VBoxDefs::GUI_AutoresizeGuest, 1581 mVmAutoresizeGuestAction->isChecked() ? "on" : "off"); 1582 machine.SetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide, 1583 mMiniToolBar->isAutoHide() ? "on" : "off"); 1584 1585 #ifdef VBOX_WITH_DEBUGGER_GUI 1586 /* Close & destroy the debugger GUI */ 1587 dbgDestroy(); 1588 #endif 1589 1590 /* Make sure all events are delievered */ 1591 qApp->processEvents(); 1592 1593 /* Notify all the top-level dialogs about closing */ 1594 emit closing(); 1595 } 1596 1597 LogFlowFunc (("accepted=%d\n", aEvent->isAccepted())); 1598 LogFlowFuncLeave(); 195 void UIMachine::enterBaseVisualState() 196 { 197 sltChangeVisualState(UIVisualStateType_Normal); 1599 198 } 1600 199 1601 #ifdef Q_WS_X11 1602 bool VBoxConsoleWnd::x11Event (XEvent *aEvent) 1603 { 1604 /* Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut, 1605 * WindowActivate and WindowDeactivate Qt events are not properly sent 1606 * on top level window (i.e. this) deactivation. The fix is to substiute 1607 * the mode in FocusOut X11 event structure to NotifyNormal to cause 1608 * Qt to process it as desired. */ 1609 if (mConsole && aEvent->type == FocusOut) 1610 { 1611 if (aEvent->xfocus.mode == NotifyWhileGrabbed && 1612 (aEvent->xfocus.detail == NotifyAncestor || 1613 aEvent->xfocus.detail == NotifyInferior || 1614 aEvent->xfocus.detail == NotifyNonlinear)) 1615 { 1616 aEvent->xfocus.mode = NotifyNormal; 1617 } 1618 } 1619 return false; 1620 } 1621 #endif 1622 1623 /** 1624 * Sets the strings of the subwidgets using the current 1625 * language. 1626 */ 1627 void VBoxConsoleWnd::retranslateUi() 1628 { 1629 #ifdef VBOX_OSE 1630 mCaptionPrefix = tr ("VirtualBox OSE"); 1631 #else 1632 mCaptionPrefix = tr ("Sun VirtualBox"); 1633 #endif 1634 1635 #ifdef VBOX_BLEEDING_EDGE 1636 mCaptionPrefix += tr (" EXPERIMENTAL build %1r%2 - %3").arg (RTBldCfgVersion()).arg (RTBldCfgRevisionStr()).arg (VBOX_BLEEDING_EDGE); 1637 #endif 1638 /* 1639 * Note: All action shortcuts should be added to the menu text in the 1640 * form of "\tHost+<Key>" where <Key> is the shortcut key according 1641 * to regular QKeySequence rules. No translation of the "Host" word is 1642 * allowed (VBoxConsoleView relies on its spelling). setAccel() must not 1643 * be used. Unfortunately on the Mac the "host" string is silently removed 1644 * & the key is created as an global shortcut. So every e.g. F key stroke 1645 * in the vm leads to a menu call of the F entry. Mysteriously the 1646 * associated action isn't started. As a workaround the Host+<key> is 1647 * written in braces after the menu text. 1648 */ 1649 1650 /* VM actions */ 1651 #ifdef Q_WS_MAC 1652 qt_set_sequence_auto_mnemonic (false); 1653 #endif 1654 1655 mVmDisMouseIntegrMenu->setToolTip (tr ("Mouse Integration", "enable/disable...")); 1656 #if 0 /* TODO: Allow to setup status-bar! */ 1657 mVmAutoresizeMenu->setToolTip (tr ("Auto-resize Guest Display", "enable/disable...")); 1658 #endif 1659 1660 mVmFullscreenAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Fullscreen Mode"), "F")); 1661 mVmFullscreenAction->setStatusTip (tr ("Switch to fullscreen mode" )); 1662 1663 mVmSeamlessAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Seam&less Mode"), "L")); 1664 mVmSeamlessAction->setStatusTip (tr ("Switch to seamless desktop integration mode")); 1665 1666 mVmAutoresizeGuestAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Auto-resize &Guest Display"), "G")); 1667 mVmAutoresizeGuestAction->setStatusTip (tr ("Automatically resize the guest display when the " 1668 "window is resized (requires Guest Additions)")); 1669 1670 mVmAdjustWindowAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Adjust Window Size"), "A")); 1671 mVmAdjustWindowAction->setStatusTip (tr ("Adjust window size and position to best fit the guest display")); 1672 1673 /* mVmDisableMouseIntegrAction is set up in updateAppearanceOf() */ 1674 1675 mVmTypeCADAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Del"), "Del")); 1676 mVmTypeCADAction->setStatusTip (tr ("Send the Ctrl-Alt-Del sequence to the virtual machine")); 1677 1678 #if defined(Q_WS_X11) 1679 mVmTypeCABSAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Backspace"), "Backspace")); 1680 mVmTypeCABSAction->setStatusTip (tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine")); 1681 #endif 1682 1683 mVmTakeSnapshotAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Take &Snapshot..."), "S")); 1684 mVmTakeSnapshotAction->setStatusTip (tr ("Take a snapshot of the virtual machine")); 1685 1686 mVmShowInformationDlgAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Session I&nformation Dialog"), "N")); 1687 mVmShowInformationDlgAction->setStatusTip (tr ("Show Session Information Dialog")); 1688 1689 mVmResetAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Reset"), "R")); 1690 mVmResetAction->setStatusTip (tr ("Reset the virtual machine")); 1691 1692 /* mVmPauseAction is set up in updateAppearanceOf() */ 1693 1694 #ifdef Q_WS_MAC 1695 /* Host+H is Hide on the mac */ 1696 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "U")); 1697 #else /* Q_WS_MAC */ 1698 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "H")); 1699 #endif /* !Q_WS_MAC */ 1700 mVmACPIShutdownAction->setStatusTip (tr ("Send the ACPI Power Button press event to the virtual machine")); 1701 1702 mVmCloseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Close..." ), "Q")); 1703 mVmCloseAction->setStatusTip (tr ("Close the virtual machine")); 1704 mVmCloseAction->setMenuRole (QAction::QuitRole); 1705 1706 /* Devices actions */ 1707 mDevicesCDMenu->setTitle (tr ("&CD/DVD Devices")); 1708 mDevicesFDMenu->setTitle (tr ("&Floppy Devices")); 1709 1710 mDevicesNetworkDialogAction->setText (tr ("&Network Adapters...")); 1711 mDevicesNetworkDialogAction->setStatusTip (tr ("Change the settings of network adapters")); 1712 1713 mDevicesSFDialogAction->setText (tr ("&Shared Folders...")); 1714 mDevicesSFDialogAction->setStatusTip (tr ("Create or modify shared folders")); 1715 1716 mDevicesSwitchVrdpAction->setText (tr ("&Remote Display")); 1717 mDevicesSwitchVrdpAction->setStatusTip (tr ("Enable or disable remote desktop (RDP) connections to this machine")); 1718 #if 0 /* TODO: Allow to setup status-bar! */ 1719 mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server", "enable/disable...")); 1720 #endif 1721 1722 mDevicesInstallGuestToolsAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Install Guest Additions..."), "D")); 1723 mDevicesInstallGuestToolsAction->setStatusTip (tr ("Mount the Guest Additions installation image")); 1724 1725 mDevicesUSBMenu->setTitle (tr ("&USB Devices")); 1726 1727 #ifdef VBOX_WITH_DEBUGGER_GUI 1728 /* Debug actions */ 1729 if (mDbgStatisticsAction) 1730 mDbgStatisticsAction->setText (tr ("&Statistics...", "debug action")); 1731 if (mDbgCommandLineAction) 1732 mDbgCommandLineAction->setText (tr ("&Command Line...", "debug action")); 1733 if (mDbgLoggingAction) 1734 mDbgLoggingAction->setText (tr ("&Logging...", "debug action")); 1735 #endif 1736 1737 /* Help actions */ 1738 mHelpActions.retranslateUi(); 1739 1740 /* Main menu & seamless popup menu */ 1741 mVMMenu->setTitle (tr ("&Machine")); 1742 // mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png")); 1743 1744 mVMMenuMini->setTitle (tr ("&Machine")); 1745 1746 mDevicesMenu->setTitle (tr ("&Devices")); 1747 // mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png")); 1748 1749 #ifdef VBOX_WITH_DEBUGGER_GUI 1750 if (vboxGlobal().isDebuggerEnabled()) 1751 mDbgMenu->setTitle (tr ("De&bug")); 1752 #endif 1753 mHelpMenu->setTitle (tr ("&Help")); 1754 // mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png")); 1755 1756 /* Status bar widgets */ 1757 mMouseLed->setToolTip ( 1758 tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>" 1759 "<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>" 1760 "<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>" 1761 "<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>" 1762 "<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>" 1763 "<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>" 1764 "Note that the mouse integration feature requires Guest Additions to be installed in the guest OS.")); 1765 mHostkeyLed->setToolTip ( 1766 tr ("Indicates whether the keyboard is captured by the guest OS " 1767 "(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>).")); 1768 mHostkeyName->setToolTip ( 1769 tr ("Shows the currently assigned Host key.<br>" 1770 "This key, when pressed alone, toggles the keyboard and mouse " 1771 "capture state. It can also be used in combination with other keys " 1772 "to quickly perform actions from the main menu.")); 1773 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 1774 1775 #if 0 /* TODO: Allow to setup status-bar! */ 1776 mAutoresizeLed->setToolTip ( 1777 tr ("Indicates whether the guest display auto-resize function is On " 1778 "(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). " 1779 "Note that this function requires Guest Additions to be installed in the guest OS.")); 1780 #endif 1781 1782 updateAppearanceOf (AllStuff); 1783 } 1784 1785 void VBoxConsoleWnd::finalizeOpenView() 1786 { 1787 LogFlowFuncEnter(); 1788 1789 /* Notify the console scroll-view about the console-window is opened. */ 1790 mConsole->onViewOpened(); 1791 1792 bool saved = mMachineState == KMachineState_Saved; 1793 1794 CMachine machine = mSession.GetMachine(); 1795 CConsole console = mConsole->console(); 1796 1797 if (mIsFirstTimeStarted) 1798 { 1799 UIFirstRunWzd wzd (this, machine); 1800 wzd.exec(); 1801 1802 /* Remove GUI_FirstRun extra data key from the machine settings 1803 * file after showing the wizard once. */ 1804 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 1805 } 1806 1807 /* Start the VM */ 1808 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 1809 console.PowerUpPaused() : console.PowerUp(); 1810 1811 /* Check for an immediate failure */ 1812 if (!console.isOk()) 1813 { 1814 vboxProblem().cannotStartMachine (console); 1815 /* close this window (this will call closeView()) */ 1816 close(); 1817 1818 LogFlowFunc (("Error starting VM\n")); 1819 LogFlowFuncLeave(); 1820 return; 1821 } 1822 1823 mConsole->attach(); 1824 1825 /* Disable auto closure because we want to have a chance to show the 1826 * error dialog on startup failure */ 1827 mNoAutoClose = true; 1828 1829 /* show the "VM starting / restoring" progress dialog */ 1830 1831 if (saved) 1832 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1833 else 1834 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1835 1836 if (progress.GetResultCode() != 0) 1837 { 1838 vboxProblem().cannotStartMachine (progress); 1839 /* close this window (this will call closeView()) */ 1840 close(); 1841 1842 LogFlowFunc (("Error starting VM\n")); 1843 LogFlowFuncLeave(); 1844 return; 1845 } 1846 1847 mNoAutoClose = false; 1848 1849 /* Check if we missed a really quick termination after successful 1850 * startup, and process it if we did. */ 1851 if ( mMachineState == KMachineState_PoweredOff 1852 || mMachineState == KMachineState_Saved 1853 || mMachineState == KMachineState_Teleported 1854 || mMachineState == KMachineState_Aborted 1855 ) 1856 { 1857 close(); 1858 LogFlowFuncLeave(); 1859 return; 1860 } 1861 1862 /* Currently the machine is started and the guest API could be used... 1863 * Checking if the fullscreen mode should be activated */ 1864 QString str = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 1865 if (str == "on") 1866 mVmFullscreenAction->setChecked (true); 1867 1868 /* If seamless mode should be enabled then check if it is enabled 1869 * currently and re-enable it if seamless is supported */ 1870 if (mVmSeamlessAction->isChecked() && mIsSeamlessSupported && mIsGraphicsSupported) 1871 toggleFullscreenMode (true, true); 1872 #ifdef VBOX_WITH_DEBUGGER_GUI 1873 /* Open the debugger in "full screen" mode requested by the user. */ 1874 else if (vboxGlobal().isDebuggerAutoShowEnabled()) 1875 { 1876 /* console in upper left corner of the desktop. */ 1877 QRect rct (0, 0, 0, 0); 1878 QDesktopWidget *desktop = QApplication::desktop(); 1879 if (desktop) 1880 rct = desktop->availableGeometry(pos()); 1881 move (QPoint (rct.x(), rct.y())); 1882 1883 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled()) 1884 dbgShowStatistics(); 1885 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled()) 1886 dbgShowCommandLine(); 1887 1888 if (!vboxGlobal().isStartPausedEnabled()) 1889 mConsole->pause (false); 1890 } 1891 #endif 1892 1893 mIsOpenViewFinished = true; 1894 LogFlowFuncLeave(); 1895 1896 #ifdef VBOX_WITH_UPDATE_REQUEST 1897 vboxGlobal().showUpdateDialog (false /* aForce */); 1898 #endif 1899 1900 /* Finally check the status of required features. */ 1901 checkRequiredFeatures(); 1902 1903 /* Re-request all the static values finally after 1904 * view is really opened and attached. */ 1905 updateAppearanceOf (VirtualizationStuff); 1906 } 1907 1908 /** 1909 * Helper to safely close the main console window. 1910 * 1911 * This method ensures that close() will not be called if there is some 1912 * modal widget currently being executed, as it can cause uninitialization 1913 * at the point of code where it is not expected at all (example: 1914 * VBoxConsoleView::mouseEvent() calling 1915 * VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to 1916 * close the current modal widget is done and tryClose() is rescheduled for 1917 * later execution using a single-shot zero timer. 1918 * 1919 * In particular, this method is used by updateMachineState() when the VM 1920 * goes offline, which can even happen if we are inside the modal event loop, 1921 * (for example, the VM has been externally powered off or the guest OS 1922 * has initiated a shutdown procedure). 1923 */ 1924 void VBoxConsoleWnd::tryClose() 1925 { 1926 /* First close any open modal & popup widgets. Use a single shot with 1927 * timeout 0 to allow the widgets to cleany close and test then again. If 1928 * all open widgets are closed destroy ourself. */ 1929 QWidget *widget = QApplication::activeModalWidget() ? 1930 QApplication::activeModalWidget() : 1931 QApplication::activePopupWidget() ? 1932 QApplication::activePopupWidget() : 0; 1933 if (widget) 1934 { 1935 widget->close(); 1936 QTimer::singleShot (0, this, SLOT (tryClose())); 1937 } 1938 else 1939 close(); 1940 } 1941 1942 void VBoxConsoleWnd::vmFullscreen (bool aOn) 1943 { 1944 bool ok = toggleFullscreenMode (aOn, false /* aSeamless */); 1945 if (!ok) 1946 { 1947 /* On failure, restore the previous button state */ 1948 mVmFullscreenAction->blockSignals (true); 1949 mVmFullscreenAction->setChecked (!aOn); 1950 mVmFullscreenAction->blockSignals (false); 1951 } 1952 } 1953 1954 void VBoxConsoleWnd::vmSeamless (bool aOn) 1955 { 1956 /* Check if it is possible to enter/leave seamless mode */ 1957 if ((mIsSeamlessSupported && mIsGraphicsSupported) || !aOn) 1958 { 1959 bool ok = toggleFullscreenMode (aOn, true /* aSeamless */); 1960 if (!ok) 1961 { 1962 /* On failure, restore the previous button state */ 1963 mVmSeamlessAction->blockSignals (true); 1964 mVmSeamlessAction->setChecked (!aOn); 1965 mVmSeamlessAction->blockSignals (false); 1966 } 1967 } 1968 } 1969 1970 void VBoxConsoleWnd::vmAutoresizeGuest (bool on) 1971 { 1972 if (!mConsole) 1973 return; 1974 1975 #if 0 /* TODO: Allow to setup status-bar! */ 1976 mAutoresizeLed->setState (on ? 3 : 1); 1977 #endif 1978 1979 mConsole->setAutoresizeGuest (on); 1980 } 1981 1982 void VBoxConsoleWnd::vmAdjustWindow() 1983 { 1984 if (mConsole) 1985 { 1986 if (isWindowMaximized()) 1987 showNormal(); 1988 mConsole->normalizeGeometry (true /* adjustPosition */); 1989 } 1990 } 1991 1992 void VBoxConsoleWnd::vmDisableMouseIntegration (bool aOff) 1993 { 1994 if (mConsole) 1995 { 1996 mConsole->setMouseIntegrationEnabled (!aOff); 1997 updateAppearanceOf (DisableMouseIntegrAction); 1998 } 1999 } 2000 2001 void VBoxConsoleWnd::vmTypeCAD() 2002 { 2003 if (mConsole) 2004 { 2005 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2006 Assert (!keyboard.isNull()); 2007 keyboard.PutCAD(); 2008 AssertWrapperOk (keyboard); 2009 } 2010 } 2011 2012 #ifdef Q_WS_X11 2013 void VBoxConsoleWnd::vmTypeCABS() 2014 { 2015 if (mConsole) 2016 { 2017 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2018 Assert (!keyboard.isNull()); 2019 static QVector <LONG> sSequence (6); 2020 sSequence[0] = 0x1d; // Ctrl down 2021 sSequence[1] = 0x38; // Alt down 2022 sSequence[2] = 0x0E; // Backspace down 2023 sSequence[3] = 0x8E; // Backspace up 2024 sSequence[4] = 0xb8; // Alt up 2025 sSequence[5] = 0x9d; // Ctrl up 2026 keyboard.PutScancodes (sSequence); 2027 AssertWrapperOk (keyboard); 2028 } 2029 } 2030 #endif 2031 2032 void VBoxConsoleWnd::vmTakeSnapshot() 2033 { 2034 AssertReturn (mConsole, (void) 0); 2035 2036 /* remember the paused state */ 2037 bool wasPaused = mMachineState == KMachineState_Paused; 2038 if (!wasPaused) 2039 { 2040 /* Suspend the VM and ignore the close event if failed to do so. 2041 * pause() will show the error message to the user. */ 2042 if (!mConsole->pause (true)) 2043 return; 2044 } 2045 2046 CMachine machine = mSession.GetMachine(); 2047 2048 VBoxTakeSnapshotDlg dlg (this, machine); 2049 2050 QString typeId = machine.GetOSTypeId(); 2051 dlg.mLbIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 2052 2053 /* search for the max available filter index */ 2054 QString nameTemplate = tr ("Snapshot %1"); 2055 int maxSnapshotIndex = searchMaxSnapshotIndex (machine, machine.GetSnapshot (QString()), nameTemplate); 2056 dlg.mLeName->setText (nameTemplate.arg (++ maxSnapshotIndex)); 2057 2058 if (dlg.exec() == QDialog::Accepted) 2059 { 2060 CConsole console = mSession.GetConsole(); 2061 2062 CProgress progress = console.TakeSnapshot (dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 2063 2064 if (console.isOk()) 2065 { 2066 /* Show the "Taking Snapshot" progress dialog */ 2067 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 2068 2069 if (progress.GetResultCode() != 0) 2070 vboxProblem().cannotTakeSnapshot (progress); 2071 } 2072 else 2073 vboxProblem().cannotTakeSnapshot (console); 2074 } 2075 2076 /* Restore the running state if needed */ 2077 if (!wasPaused) 2078 mConsole->pause (false); 2079 } 2080 2081 void VBoxConsoleWnd::vmShowInfoDialog() 2082 { 2083 VBoxVMInformationDlg::createInformationDlg (mSession, mConsole); 2084 } 2085 2086 void VBoxConsoleWnd::vmReset() 2087 { 2088 if (mConsole) 2089 { 2090 if (vboxProblem().confirmVMReset (this)) 2091 mConsole->console().Reset(); 2092 } 2093 } 2094 2095 void VBoxConsoleWnd::vmPause (bool aOn) 2096 { 2097 if (mConsole) 2098 { 2099 mConsole->pause (aOn); 2100 updateAppearanceOf (PauseAction); 2101 } 2102 } 2103 2104 void VBoxConsoleWnd::vmACPIShutdown() 2105 { 2106 if (!mSession.GetConsole().GetGuestEnteredACPIMode()) 2107 return vboxProblem().cannotSendACPIToMachine(); 2108 2109 if (mConsole) 2110 { 2111 CConsole console = mConsole->console(); 2112 console.PowerButton(); 2113 if (!console.isOk()) 2114 vboxProblem().cannotACPIShutdownMachine (console); 2115 } 2116 } 2117 2118 void VBoxConsoleWnd::vmClose() 2119 { 2120 if (mConsole) 2121 close(); 2122 } 2123 2124 void VBoxConsoleWnd::devicesSwitchVrdp (bool aOn) 2125 { 2126 if (!mConsole) return; 2127 2128 CVRDPServer vrdpServer = mSession.GetMachine().GetVRDPServer(); 2129 /* This method should not be executed if vrdpServer is null */ 2130 Assert (!vrdpServer.isNull()); 2131 2132 vrdpServer.SetEnabled (aOn); 2133 updateAppearanceOf (VRDPStuff); 2134 } 2135 2136 void VBoxConsoleWnd::devicesOpenNetworkDialog() 2137 { 2138 if (!mConsole) return; 2139 2140 VBoxNetworkDialog dlg (mConsole, mSession); 2141 dlg.exec(); 2142 } 2143 2144 void VBoxConsoleWnd::devicesOpenSFDialog() 2145 { 2146 if (!mConsole) return; 2147 2148 VBoxSFDialog dlg (mConsole, mSession); 2149 dlg.exec(); 2150 } 2151 2152 void VBoxConsoleWnd::devicesInstallGuestAdditions() 2153 { 2154 char szAppPrivPath [RTPATH_MAX]; 2155 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); 2156 AssertRC (rc); 2157 2158 QString src1 = QString (szAppPrivPath) + "/VBoxGuestAdditions.iso"; 2159 QString src2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 2160 2161 /* Check the standard image locations */ 2162 if (QFile::exists (src1)) 2163 return installGuestAdditionsFrom (src1); 2164 else if (QFile::exists (src2)) 2165 return installGuestAdditionsFrom (src2); 2166 2167 /* Check for the already registered image */ 2168 CVirtualBox vbox = vboxGlobal().virtualBox(); 2169 QString name = QString ("VBoxGuestAdditions_%1.iso").arg (vbox.GetVersion().remove ("_OSE")); 2170 2171 CMediumVector vec = vbox.GetDVDImages(); 2172 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 2173 { 2174 QString path = it->GetLocation(); 2175 /* Compare the name part ignoring the file case */ 2176 QString fn = QFileInfo (path).fileName(); 2177 if (RTPathCompare (name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 2178 return installGuestAdditionsFrom (path); 2179 } 2180 2181 /* Download the required image */ 2182 int result = vboxProblem().cannotFindGuestAdditions ( 2183 QDir::toNativeSeparators (src1), QDir::toNativeSeparators (src2)); 2184 if (result == QIMessageBox::Yes) 2185 { 2186 QString source = QString ("http://download.virtualbox.org/virtualbox/%1/") 2187 .arg (vbox.GetVersion().remove ("_OSE")) + name; 2188 QString target = QDir (vboxGlobal().virtualBox().GetHomeFolder()) 2189 .absoluteFilePath (name); 2190 2191 VBoxAdditionsDownloader *dl = 2192 new VBoxAdditionsDownloader (source, target, mDevicesInstallGuestToolsAction); 2193 statusBar()->addWidget (dl, 0); 2194 dl->start(); 2195 } 2196 } 2197 2198 void VBoxConsoleWnd::prepareStorageMenu() 2199 { 2200 QMenu *menu = qobject_cast <QMenu*> (sender()); 2201 Assert (menu); 2202 menu->clear(); 2203 2204 KDeviceType deviceType = menu == mDevicesCDMenu ? KDeviceType_DVD : 2205 menu == mDevicesFDMenu ? KDeviceType_Floppy : 2206 KDeviceType_Null; 2207 Assert (deviceType != KDeviceType_Null); 2208 2209 VBoxDefs::MediumType mediumType = menu == mDevicesCDMenu ? VBoxDefs::MediumType_DVD : 2210 menu == mDevicesFDMenu ? VBoxDefs::MediumType_Floppy : 2211 VBoxDefs::MediumType_Invalid; 2212 Assert (mediumType != VBoxDefs::MediumType_Invalid); 2213 2214 CMachine machine = mSession.GetMachine(); 2215 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 2216 foreach (const CMediumAttachment &attachment, attachments) 2217 { 2218 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 2219 if ( !controller.isNull() 2220 && (attachment.GetType() == deviceType)) 2221 { 2222 /* Attachment menu item */ 2223 QMenu *attachmentMenu = 0; 2224 if (menu->menuAction()->data().toInt() > 1) 2225 { 2226 attachmentMenu = new QMenu (menu); 2227 attachmentMenu->setTitle (QString ("%1 (%2)").arg (controller.GetName()) 2228 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), 2229 attachment.GetPort(), 2230 attachment.GetDevice())))); 2231 switch (controller.GetBus()) 2232 { 2233 case KStorageBus_IDE: 2234 attachmentMenu->setIcon (QIcon (":/ide_16px.png")); break; 2235 case KStorageBus_SATA: 2236 attachmentMenu->setIcon (QIcon (":/sata_16px.png")); break; 2237 case KStorageBus_SCSI: 2238 attachmentMenu->setIcon (QIcon (":/scsi_16px.png")); break; 2239 case KStorageBus_Floppy: 2240 attachmentMenu->setIcon (QIcon (":/floppy_16px.png")); break; 2241 default: 2242 break; 2243 } 2244 menu->addMenu (attachmentMenu); 2245 } 2246 else attachmentMenu = menu; 2247 2248 /* Mount Medium actions */ 2249 CMediumVector mediums; 2250 switch (mediumType) 2251 { 2252 case VBoxDefs::MediumType_DVD: 2253 mediums += vboxGlobal().virtualBox().GetHost().GetDVDDrives(); 2254 mediums += vboxGlobal().virtualBox().GetDVDImages(); 2255 break; 2256 case VBoxDefs::MediumType_Floppy: 2257 mediums += vboxGlobal().virtualBox().GetHost().GetFloppyDrives(); 2258 mediums += vboxGlobal().virtualBox().GetFloppyImages(); 2259 break; 2260 default: 2261 break; 2262 } 2263 2264 int mediumsToBeShown = 0; 2265 const int maxMediumsToBeShown = 5; 2266 CMedium currentMedium = attachment.GetMedium(); 2267 QString currentId = currentMedium.isNull() ? QString::null : currentMedium.GetId(); 2268 bool currentUsed = false; 2269 foreach (CMedium medium, mediums) 2270 { 2271 bool isMediumUsed = false; 2272 foreach (const CMediumAttachment &otherAttachment, attachments) 2273 { 2274 if (otherAttachment != attachment) 2275 { 2276 CMedium otherMedium = otherAttachment.GetMedium(); 2277 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 2278 { 2279 isMediumUsed = true; 2280 break; 2281 } 2282 } 2283 } 2284 if (!isMediumUsed) 2285 { 2286 if (!currentUsed && !currentMedium.isNull() && mediumsToBeShown == maxMediumsToBeShown - 1) 2287 medium = currentMedium; 2288 2289 if (medium.GetId() == currentId) 2290 currentUsed = true; 2291 2292 QAction *mountMediumAction = new QAction (VBoxMedium (medium, mediumType).name(), attachmentMenu); 2293 mountMediumAction->setCheckable (true); 2294 mountMediumAction->setChecked (!currentMedium.isNull() && medium.GetId() == currentId); 2295 mountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2296 attachment.GetPort(), 2297 attachment.GetDevice(), 2298 medium.GetId()))); 2299 connect (mountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2300 attachmentMenu->addAction (mountMediumAction); 2301 ++ mediumsToBeShown; 2302 if (mediumsToBeShown == maxMediumsToBeShown) 2303 break; 2304 } 2305 } 2306 2307 /* Virtual Media Manager action */ 2308 QAction *callVMMAction = new QAction (attachmentMenu); 2309 callVMMAction->setIcon (QIcon (":/diskimage_16px.png")); 2310 callVMMAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2311 attachment.GetPort(), 2312 attachment.GetDevice(), 2313 mediumType))); 2314 connect (callVMMAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2315 attachmentMenu->addAction (callVMMAction); 2316 2317 /* Separator */ 2318 attachmentMenu->addSeparator(); 2319 2320 /* Unmount Medium action */ 2321 QAction *unmountMediumAction = new QAction (attachmentMenu); 2322 unmountMediumAction->setEnabled (!currentMedium.isNull()); 2323 unmountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2324 attachment.GetPort(), 2325 attachment.GetDevice()))); 2326 connect (unmountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2327 attachmentMenu->addAction (unmountMediumAction); 2328 2329 /* Switch CD/FD naming */ 2330 switch (mediumType) 2331 { 2332 case VBoxDefs::MediumType_DVD: 2333 callVMMAction->setText (tr ("More CD/DVD Images...")); 2334 unmountMediumAction->setText (tr ("Unmount CD/DVD Device")); 2335 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/cd_unmount_16px.png", 2336 ":/cd_unmount_dis_16px.png")); 2337 break; 2338 case VBoxDefs::MediumType_Floppy: 2339 callVMMAction->setText (tr ("More Floppy Images...")); 2340 unmountMediumAction->setText (tr ("Unmount Floppy Device")); 2341 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/fd_unmount_16px.png", 2342 ":/fd_unmount_dis_16px.png")); 2343 break; 2344 default: 2345 break; 2346 } 2347 } 2348 } 2349 2350 if (menu->menuAction()->data().toInt() == 0) 2351 { 2352 /* Empty menu item */ 2353 Assert (menu->isEmpty()); 2354 QAction *emptyMenuAction = new QAction (menu); 2355 emptyMenuAction->setEnabled (false); 2356 switch (mediumType) 2357 { 2358 case VBoxDefs::MediumType_DVD: 2359 emptyMenuAction->setText (tr ("No CD/DVD Devices Attached")); 2360 break; 2361 case VBoxDefs::MediumType_Floppy: 2362 emptyMenuAction->setText (tr ("No Floppy Devices Attached")); 2363 break; 2364 default: 2365 break; 2366 } 2367 emptyMenuAction->setIcon (VBoxGlobal::iconSet (":/delete_16px.png", ":/delete_dis_16px.png")); 2368 menu->addAction (emptyMenuAction); 2369 } 2370 } 2371 2372 void VBoxConsoleWnd::prepareNetworkMenu() 2373 { 2374 mDevicesNetworkMenu->clear(); 2375 mDevicesNetworkMenu->addAction (mDevicesNetworkDialogAction); 2376 } 2377 2378 void VBoxConsoleWnd::prepareSFMenu() 2379 { 2380 mDevicesSFMenu->clear(); 2381 mDevicesSFMenu->addAction (mDevicesSFDialogAction); 2382 } 2383 2384 void VBoxConsoleWnd::mountMedium() 2385 { 2386 /* Get sender action */ 2387 QAction *action = qobject_cast <QAction*> (sender()); 2388 Assert (action); 2389 2390 /* Get current machine */ 2391 CMachine machine = mSession.GetMachine(); 2392 2393 /* Get mount-target */ 2394 MountTarget target = action->data().value <MountTarget>(); 2395 2396 /* Current mount-target attributes */ 2397 CMediumAttachment currentAttachment = machine.GetMediumAttachment (target.name, target.port, target.device); 2398 CMedium currentMedium = currentAttachment.GetMedium(); 2399 QString currentId = currentMedium.isNull() ? QString ("") : currentMedium.GetId(); 2400 2401 /* New mount-target attributes */ 2402 QString newId = QString (""); 2403 bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid; 2404 2405 /* Open Virtual Media Manager to select image id */ 2406 if (selectWithMediaManager) 2407 { 2408 /* Search for already used images */ 2409 QStringList usedImages; 2410 foreach (const CMediumAttachment &attachment, machine.GetMediumAttachments()) 2411 { 2412 CMedium medium = attachment.GetMedium(); 2413 if (attachment != currentAttachment && !medium.isNull() && !medium.GetHostDrive()) 2414 usedImages << medium.GetId(); 2415 } 2416 /* Open VMM Dialog */ 2417 VBoxMediaManagerDlg dlg (this); 2418 dlg.setup (target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages); 2419 if (dlg.exec() == QDialog::Accepted) 2420 newId = dlg.selectedId(); 2421 else return; 2422 } 2423 /* Use medium which was sent */ 2424 else if (!target.id.isNull() && target.id != currentId) 2425 newId = target.id; 2426 2427 bool mount = !newId.isEmpty(); 2428 2429 /* Remount medium to the predefined port/device */ 2430 bool wasMounted = false; 2431 machine.MountMedium (target.name, target.port, target.device, newId, false /* force */); 2432 if (machine.isOk()) 2433 wasMounted = true; 2434 else 2435 { 2436 /* Ask for force remounting */ 2437 if (vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok) 2438 { 2439 /* Force remount medium to the predefined port/device. */ 2440 machine.MountMedium (target.name, target.port, target.device, newId, true /* force */); 2441 if (machine.isOk()) 2442 wasMounted = true; 2443 else 2444 vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */); 2445 } 2446 } 2447 2448 /* Save medium mounted at runtime */ 2449 if (wasMounted && mIsAutoSaveMedia) 2450 { 2451 machine.SaveSettings(); 2452 if (!machine.isOk()) 2453 vboxProblem().cannotSaveMachineSettings (machine); 2454 } 2455 } 2456 2457 /** 2458 * Attach/Detach selected USB Device. 2459 */ 2460 void VBoxConsoleWnd::switchUSB (QAction *aAction) 2461 { 2462 if (!mConsole) return; 2463 2464 CConsole console = mSession.GetConsole(); 2465 AssertWrapperOk (mSession); 2466 2467 CUSBDevice usb = mDevicesUSBMenu->getUSB (aAction); 2468 /* if null then some other item but a USB device is selected */ 2469 if (usb.isNull()) 2470 return; 2471 2472 if (!aAction->isChecked()) 2473 { 2474 console.DetachUSBDevice (usb.GetId()); 2475 if (!console.isOk()) 2476 { 2477 /// @todo (r=dmik) the dialog should be either modeless 2478 // or we have to pause the VM 2479 vboxProblem().cannotDetachUSBDevice (console, vboxGlobal().details (usb)); 2480 } 2481 } 2482 else 2483 { 2484 console.AttachUSBDevice (usb.GetId()); 2485 if (!console.isOk()) 2486 { 2487 /// @todo (r=dmik) the dialog should be either modeless 2488 // or we have to pause the VM 2489 vboxProblem().cannotAttachUSBDevice (console, vboxGlobal().details (usb)); 2490 } 2491 } 2492 } 2493 2494 void VBoxConsoleWnd::showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent) 2495 { 2496 if (aInd == mCDLed) 2497 { 2498 mDevicesCDMenu->exec (aEvent->globalPos()); 2499 } 2500 #if 0 /* TODO: Allow to setup status-bar! */ 2501 else if (aInd == mFDLed) 2502 { 2503 mDevicesFDMenu->exec (aEvent->globalPos()); 2504 } 2505 #endif 2506 else if (aInd == mNetLed) 2507 { 2508 if (mDevicesNetworkMenu->isEnabled()) 2509 mDevicesNetworkMenu->exec (aEvent->globalPos()); 2510 } 2511 else if (aInd == mUSBLed) 2512 { 2513 if (mDevicesUSBMenu->isEnabled()) 2514 mDevicesUSBMenu->exec (aEvent->globalPos()); 2515 } 2516 else if (aInd == mSFLed) 2517 { 2518 if (mDevicesSFMenu->isEnabled()) 2519 mDevicesSFMenu->exec (aEvent->globalPos()); 2520 } 2521 else if (aInd == mMouseLed) 2522 { 2523 mVmDisMouseIntegrMenu->exec (aEvent->globalPos()); 2524 } 2525 #if 0 /* TODO: Allow to setup status-bar! */ 2526 else if (aInd == mVrdpLed) 2527 { 2528 mDevicesVRDPMenu->exec (aEvent->globalPos()); 2529 } 2530 else if (aInd == mAutoresizeLed) 2531 { 2532 mVmAutoresizeMenu->exec (aEvent->globalPos()); 2533 } 2534 #endif 2535 } 2536 2537 void VBoxConsoleWnd::updateDeviceLights() 2538 { 2539 if (mConsole) 2540 { 2541 CConsole &console = mConsole->console(); 2542 int st; 2543 if (mHDLed->state() != KDeviceActivity_Null) 2544 { 2545 st = console.GetDeviceActivity (KDeviceType_HardDisk); 2546 if (mHDLed->state() != st) 2547 mHDLed->setState (st); 2548 } 2549 if (mCDLed->state() != KDeviceActivity_Null) 2550 { 2551 st = console.GetDeviceActivity (KDeviceType_DVD); 2552 if (mCDLed->state() != st) 2553 mCDLed->setState (st); 2554 } 2555 #if 0 /* TODO: Allow to setup status-bar! */ 2556 if (mFDLed->state() != KDeviceActivity_Null) 2557 { 2558 st = console.GetDeviceActivity (KDeviceType_Floppy); 2559 if (mFDLed->state() != st) 2560 mFDLed->setState (st); 2561 } 2562 #endif 2563 if (mNetLed->state() != KDeviceActivity_Null) 2564 { 2565 st = console.GetDeviceActivity (KDeviceType_Network); 2566 if (mNetLed->state() != st) 2567 mNetLed->setState (st); 2568 } 2569 if (mUSBLed->state() != KDeviceActivity_Null) 2570 { 2571 st = console.GetDeviceActivity (KDeviceType_USB); 2572 if (mUSBLed->state() != st) 2573 mUSBLed->setState (st); 2574 } 2575 if (mSFLed->state() != KDeviceActivity_Null) 2576 { 2577 st = console.GetDeviceActivity (KDeviceType_SharedFolder); 2578 if (mSFLed->state() != st) 2579 mSFLed->setState (st); 2580 } 2581 } 2582 } 2583 2584 void VBoxConsoleWnd::updateMachineState (KMachineState aState) 2585 { 2586 bool guruMeditation = false; 2587 2588 if (mConsole && mMachineState != aState) 2589 { 2590 switch (aState) 2591 { 2592 case KMachineState_Stuck: 2593 { 2594 guruMeditation = true; 2595 break; 2596 } 2597 case KMachineState_Paused: 2598 { 2599 if (!mVmPauseAction->isChecked()) 2600 mVmPauseAction->setChecked (true); 2601 break; 2602 } 2603 case KMachineState_Running: 2604 case KMachineState_Teleporting: /** @todo Live Migration: Check out this. */ 2605 case KMachineState_LiveSnapshotting: 2606 { 2607 if ( ( mMachineState == KMachineState_Paused 2608 || mMachineState == KMachineState_TeleportingPausedVM) 2609 && mVmPauseAction->isChecked() 2610 ) 2611 mVmPauseAction->setChecked (false); 2612 break; 2613 } 2614 #ifdef Q_WS_X11 2615 case KMachineState_Starting: 2616 case KMachineState_Restoring: 2617 case KMachineState_TeleportingIn: 2618 { 2619 /* The keyboard handler may wish to do some release logging 2620 on startup. Tell it that the logger is now active. */ 2621 doXKeyboardLogging (QX11Info::display()); 2622 break; 2623 } 2624 #endif 2625 default: 2626 break; 2627 } 2628 2629 bool isRunningOrPaused = aState == KMachineState_Running 2630 || aState == KMachineState_Teleporting 2631 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2632 || aState == KMachineState_Paused; 2633 2634 /* Enable/Disable actions that are not managed by updateAppearanceOf() */ 2635 2636 mRunningActions->setEnabled ( aState == KMachineState_Running 2637 || aState == KMachineState_Teleporting 2638 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2639 ); 2640 mRunningOrPausedActions->setEnabled (isRunningOrPaused); 2641 2642 mMachineState = aState; 2643 2644 updateAppearanceOf (Caption | 2645 HardDiskStuff | DVDStuff | FloppyStuff | 2646 NetworkStuff | USBStuff | VRDPStuff | 2647 PauseAction | DisableMouseIntegrAction); 2648 2649 if ( aState == KMachineState_PoweredOff 2650 || aState == KMachineState_Saved 2651 || aState == KMachineState_Teleported 2652 || aState == KMachineState_Aborted 2653 ) 2654 { 2655 /* VM has been powered off or saved or aborted, no matter 2656 * internally or externally -- we must *safely* close the console 2657 * window unless auto closure is disabled. */ 2658 if (!mNoAutoClose) 2659 tryClose(); 2660 } 2661 } 2662 2663 if (guruMeditation) 2664 { 2665 mConsole->setIgnoreGuestResize (true); 2666 2667 CConsole console = mConsole->console(); 2668 QString logFolder = console.GetMachine().GetLogFolder(); 2669 2670 /* Take the screenshot for debugging purposes and save it */ 2671 QString fname = logFolder + "/VBox.png"; 2672 2673 CDisplay dsp = console.GetDisplay(); 2674 QImage shot = QImage (dsp.GetWidth(), dsp.GetHeight(), QImage::Format_RGB32); 2675 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 2676 shot.save (QFile::encodeName (fname), "PNG"); 2677 2678 if (vboxProblem().remindAboutGuruMeditation (console, QDir::toNativeSeparators (logFolder))) 2679 { 2680 qApp->processEvents(); 2681 console.PowerDown(); 2682 if (!console.isOk()) 2683 vboxProblem().cannotStopMachine (console); 2684 } 2685 } 2686 2687 #ifdef Q_WS_MAC 2688 if (mConsole) 2689 mConsole->updateDockOverlay(); 2690 #endif 2691 } 2692 2693 void VBoxConsoleWnd::updateMouseState (int aState) 2694 { 2695 mVmDisableMouseIntegrAction->setEnabled (aState & VBoxConsoleView::MouseAbsolute); 2696 2697 if ((aState & VBoxConsoleView::MouseAbsoluteDisabled) && 2698 (aState & VBoxConsoleView::MouseAbsolute) && 2699 !(aState & VBoxConsoleView::MouseCaptured)) 2700 { 2701 mMouseLed->setState (4); 2702 } 2703 else 2704 { 2705 mMouseLed->setState (aState & (VBoxConsoleView::MouseAbsolute | VBoxConsoleView::MouseCaptured)); 2706 } 2707 } 2708 2709 void VBoxConsoleWnd::updateAdditionsState (const QString &aVersion, 2710 bool aActive, 2711 bool aSeamlessSupported, 2712 bool aGraphicsSupported) 2713 { 2714 mVmAutoresizeGuestAction->setEnabled (aActive && aGraphicsSupported); 2715 if ((mIsSeamlessSupported != aSeamlessSupported) || 2716 (mIsGraphicsSupported != aGraphicsSupported)) 2717 { 2718 mVmSeamlessAction->setEnabled (aSeamlessSupported && aGraphicsSupported); 2719 mIsSeamlessSupported = aSeamlessSupported; 2720 mIsGraphicsSupported = aGraphicsSupported; 2721 /* If seamless mode should be enabled then check if it is enabled 2722 * currently and re-enable it if open-view procedure is finished */ 2723 if (mVmSeamlessAction->isChecked() && mIsOpenViewFinished && aSeamlessSupported && aGraphicsSupported) 2724 toggleFullscreenMode (true, true); 2725 /* Disable auto-resizing if advanced graphics are not available */ 2726 mConsole->setAutoresizeGuest (mIsGraphicsSupported && mVmAutoresizeGuestAction->isChecked()); 2727 mVmAutoresizeGuestAction->setEnabled (mIsGraphicsSupported); 2728 } 2729 2730 /* Check the GA version only in case of additions are active */ 2731 if (!aActive) 2732 return; 2733 2734 /* Check the Guest Additions version and warn the user about possible 2735 * compatibility issues in case if the installed version is outdated. */ 2736 uint version = aVersion.toUInt(); 2737 QString versionStr = QString ("%1.%2") 2738 .arg (RT_HIWORD (version)).arg (RT_LOWORD (version)); 2739 QString expectedStr = QString ("%1.%2") 2740 .arg (VMMDEV_VERSION_MAJOR).arg (VMMDEV_VERSION_MINOR); /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 2741 2742 if (RT_HIWORD (version) < VMMDEV_VERSION_MAJOR) 2743 { 2744 vboxProblem().warnAboutTooOldAdditions (this, versionStr, expectedStr); 2745 } 2746 else if (RT_HIWORD (version) == VMMDEV_VERSION_MAJOR && 2747 RT_LOWORD (version) < VMMDEV_VERSION_MINOR) 2748 { 2749 vboxProblem().warnAboutOldAdditions (this, versionStr, expectedStr); 2750 } 2751 else if (version > VMMDEV_VERSION) 2752 { 2753 vboxProblem().warnAboutNewAdditions (this, versionStr, expectedStr); 2754 } 2755 } 2756 2757 void VBoxConsoleWnd::updateNetworkAdaptersState() 2758 { 2759 updateAppearanceOf (NetworkStuff); 2760 } 2761 2762 void VBoxConsoleWnd::updateUsbState() 2763 { 2764 updateAppearanceOf (USBStuff); 2765 } 2766 2767 void VBoxConsoleWnd::updateMediaDriveState (VBoxDefs::MediumType aType) 2768 { 2769 Assert (aType == VBoxDefs::MediumType_DVD || aType == VBoxDefs::MediumType_Floppy); 2770 updateAppearanceOf (aType == VBoxDefs::MediumType_DVD ? DVDStuff : 2771 aType == VBoxDefs::MediumType_Floppy ? FloppyStuff : 2772 AllStuff); 2773 } 2774 2775 void VBoxConsoleWnd::updateSharedFoldersState() 2776 { 2777 updateAppearanceOf (SharedFolderStuff); 2778 } 2779 2780 /** 2781 * This slot is called just after leaving the fullscreen/seamless mode, 2782 * when the console was resized to previous size. 2783 */ 2784 void VBoxConsoleWnd::onExitFullscreen() 2785 { 2786 mConsole->setIgnoreMainwndResize (false); 2787 } 2788 2789 void VBoxConsoleWnd::unlockActionsSwitch() 2790 { 2791 if (mIsSeamless) 2792 mVmSeamlessAction->setEnabled (true); 2793 else if (mIsFullscreen) 2794 mVmFullscreenAction->setEnabled (true); 2795 else 2796 { 2797 mVmSeamlessAction->setEnabled (mIsSeamlessSupported && mIsGraphicsSupported); 2798 mVmFullscreenAction->setEnabled (true); 2799 } 2800 2801 #ifdef Q_WS_MAC 2802 if (!mIsSeamless) 2803 { 2804 /* Fade back to the normal gamma */ 2805 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 2806 CGReleaseDisplayFadeReservation (mFadeToken); 2807 } 2808 mConsole->setMouseCoalescingEnabled (true); 2809 #endif 2810 2811 #ifdef Q_WS_X11 2812 if (vboxGlobal().isKWinManaged() && !mIsSeamless && !mIsFullscreen) 2813 { 2814 /* Workaround for a KWin bug to let console window to exit 2815 * seamless mode correctly. */ 2816 setWindowFlags(Qt::Window); 2817 setVisible(true); 2818 } 2819 #endif 2820 } 2821 2822 void VBoxConsoleWnd::mtExitMode() 2823 { 2824 if (mIsSeamless) 2825 mVmSeamlessAction->toggle(); 2826 else 2827 mVmFullscreenAction->toggle(); 2828 } 2829 2830 void VBoxConsoleWnd::mtCloseVM() 2831 { 2832 mVmCloseAction->trigger(); 2833 } 2834 2835 void VBoxConsoleWnd::mtMaskUpdate() 2836 { 2837 if (mIsSeamless) 2838 setMask (mConsole->lastVisibleRegion()); 2839 } 2840 2841 void VBoxConsoleWnd::changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent) 2842 { 2843 #ifdef Q_WS_MAC 2844 if (mConsole) 2845 { 2846 mConsole->setDockIconEnabled (aEvent.mChanged); 2847 mConsole->updateDockOverlay(); 2848 } 2849 #else 2850 Q_UNUSED (aEvent); 2851 #endif 2852 } 2853 2854 void VBoxConsoleWnd::changePresentationMode (const VBoxChangePresentationModeEvent &aEvent) 2855 { 2856 Q_UNUSED (aEvent); 2857 #ifdef Q_WS_MAC 2858 # ifdef QT_MAC_USE_COCOA 2859 if (mIsFullscreen) 2860 { 2861 /* First check if we are on the primary screen, only than the 2862 presentation mode have to be changed. */ 2863 QDesktopWidget* pDesktop = QApplication::desktop(); 2864 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 2865 { 2866 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_PresentationModeEnabled).toLower(); 2867 /* Default to false if it is an empty value */ 2868 if (testStr.isEmpty() || testStr == "false") 2869 SetSystemUIMode (kUIModeAllHidden, 0); 2870 else 2871 SetSystemUIMode (kUIModeAllSuppressed, 0); 2872 } 2873 } 2874 else 2875 SetSystemUIMode (kUIModeNormal, 0); 2876 # endif /* QT_MAC_USE_COCOA */ 2877 #endif 2878 } 2879 2880 /** 2881 * Called (on non-UI thread!) when a global GUI setting changes. 2882 */ 2883 void VBoxConsoleWnd::processGlobalSettingChange (const char * /* aPublicName */, const char * /* aName */) 2884 { 2885 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 2886 } 2887 2888 /** 2889 * This function checks the status of required features and 2890 * makes a warning and/or some action if something necessary 2891 * is not in good condition. 2892 * Does nothing if no console view was opened. 2893 */ 2894 void VBoxConsoleWnd::checkRequiredFeatures() 2895 { 2896 if (!mConsole) return; 2897 2898 CConsole console = mConsole->console(); 2899 2900 /* Check if the virtualization feature is required. */ 2901 bool is64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType ( 2902 console.GetGuest().GetOSTypeId()).GetIs64Bit(); 2903 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType ( 2904 console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 2905 Assert(!is64BitsGuest || fRecommendVirtEx); 2906 bool isVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 2907 if (fRecommendVirtEx && !isVirtEnabled) 2908 { 2909 bool ret; 2910 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost() 2911 .GetProcessorFeature (KProcessorFeature_HWVirtEx); 2912 2913 vmPause (true); 2914 2915 if (is64BitsGuest) 2916 ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported); 2917 else 2918 ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported); 2919 2920 if (ret == true) 2921 close(); 2922 else 2923 vmPause (false); 2924 } 2925 } 2926 2927 void VBoxConsoleWnd::activateUICustomizations() 2928 { 2929 VBoxGlobalSettings settings = vboxGlobal().settings(); 2930 /* Process known keys */ 2931 menuBar()->setHidden (settings.isFeatureActive ("noMenuBar")); 2932 statusBar()->setHidden (settings.isFeatureActive ("noStatusBar")); 2933 } 2934 2935 void VBoxConsoleWnd::updateAppearanceOf (int aElement) 2936 { 2937 if (!mConsole) return; 2938 2939 CMachine machine = mSession.GetMachine(); 2940 CConsole console = mConsole->console(); 2941 2942 bool isStrictRunningOrPaused = mMachineState == KMachineState_Running 2943 || mMachineState == KMachineState_Paused; 2944 bool isRunningOrPaused = isStrictRunningOrPaused 2945 || mMachineState == KMachineState_Teleporting 2946 || mMachineState == KMachineState_LiveSnapshotting; 2947 2948 if (aElement & Caption) 2949 { 2950 QString snapshotName; 2951 if (machine.GetSnapshotCount() > 0) 2952 { 2953 CSnapshot snapshot = machine.GetCurrentSnapshot(); 2954 snapshotName = " (" + snapshot.GetName() + ")"; 2955 } 2956 setWindowTitle (machine.GetName() + snapshotName + 2957 " [" + vboxGlobal().toString (mMachineState) + "] - " + 2958 mCaptionPrefix); 2959 mMiniToolBar->setDisplayText (machine.GetName() + snapshotName); 2960 } 2961 if (aElement & HardDiskStuff) 2962 { 2963 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2964 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 2965 QString data; 2966 bool attachmentsPresent = false; 2967 2968 CStorageControllerVector controllers = machine.GetStorageControllers(); 2969 foreach (const CStorageController &controller, controllers) 2970 { 2971 QString attData; 2972 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 2973 foreach (const CMediumAttachment &attachment, attachments) 2974 { 2975 if (attachment.GetType() != KDeviceType_HardDisk) 2976 continue; 2977 attData += QString ("<br> <nobr>%1: %2</nobr>") 2978 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 2979 .arg (VBoxMedium (attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 2980 attachmentsPresent = true; 2981 } 2982 if (!attData.isNull()) 2983 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 2984 } 2985 2986 if (!attachmentsPresent) 2987 data += tr ("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 2988 2989 mHDLed->setToolTip (tip.arg (data)); 2990 mHDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 2991 } 2992 if (aElement & DVDStuff) 2993 { 2994 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2995 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 2996 QString data; 2997 bool attachmentsPresent = false; 2998 2999 CStorageControllerVector controllers = machine.GetStorageControllers(); 3000 foreach (const CStorageController &controller, controllers) 3001 { 3002 QString attData; 3003 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3004 foreach (const CMediumAttachment &attachment, attachments) 3005 { 3006 if (attachment.GetType() != KDeviceType_DVD) 3007 continue; 3008 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_DVD); 3009 attData += QString ("<br> <nobr>%1: %2</nobr>") 3010 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3011 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3012 if (!vboxMedium.isNull()) 3013 attachmentsPresent = true; 3014 } 3015 if (!attData.isNull()) 3016 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3017 } 3018 3019 if (data.isNull()) 3020 data = tr ("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 3021 3022 mCDLed->setToolTip (tip.arg (data)); 3023 mCDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3024 } 3025 #if 0 /* TODO: Allow to setup status-bar! */ 3026 if (aElement & FloppyStuff) 3027 { 3028 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 3029 "of the floppy devices:</nobr>%1</p>", "FD tooltip"); 3030 QString data; 3031 bool attachmentsPresent = false; 3032 3033 CStorageControllerVector controllers = machine.GetStorageControllers(); 3034 foreach (const CStorageController &controller, controllers) 3035 { 3036 QString attData; 3037 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3038 foreach (const CMediumAttachment &attachment, attachments) 3039 { 3040 if (attachment.GetType() != KDeviceType_Floppy) 3041 continue; 3042 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_Floppy); 3043 attData += QString ("<br> <nobr>%1: %2</nobr>") 3044 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3045 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3046 if (!vboxMedium.isNull()) 3047 attachmentsPresent = true; 3048 } 3049 if (!attData.isNull()) 3050 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3051 } 3052 3053 if (data.isNull()) 3054 data = tr ("<br><nobr><b>No floppy devices attached</b></nobr>", "FD tooltip"); 3055 3056 mFDLed->setToolTip (tip.arg (data)); 3057 mFDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3058 } 3059 #endif 3060 if (aElement & NetworkStuff) 3061 { 3062 ulong maxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 3063 ulong count = 0; 3064 for (ulong slot = 0; slot < maxCount; ++ slot) 3065 if (machine.GetNetworkAdapter (slot).GetEnabled()) 3066 ++ count; 3067 mNetLed->setState (count > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 3068 3069 mDevicesNetworkDialogAction->setEnabled (isStrictRunningOrPaused && count > 0); 3070 mDevicesNetworkMenu->setEnabled (isStrictRunningOrPaused && count > 0); 3071 3072 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of the " 3073 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 3074 QString info; 3075 3076 for (ulong slot = 0; slot < maxCount; ++ slot) 3077 { 3078 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot); 3079 if (adapter.GetEnabled()) 3080 info += tr ("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 3081 .arg (slot + 1) 3082 .arg (vboxGlobal().toString (adapter.GetAttachmentType())) 3083 .arg (adapter.GetCableConnected() ? 3084 tr ("connected", "Network adapters tooltip") : 3085 tr ("disconnected", "Network adapters tooltip")); 3086 } 3087 3088 if (info.isNull()) 3089 info = tr ("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 3090 3091 mNetLed->setToolTip (tip.arg (info)); 3092 } 3093 if (aElement & USBStuff) 3094 { 3095 if (!mUSBLed->isHidden()) 3096 { 3097 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3098 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 3099 QString info; 3100 3101 CUSBController usbctl = machine.GetUSBController(); 3102 if (!usbctl.isNull() && usbctl.GetEnabled()) 3103 { 3104 mDevicesUSBMenu->setEnabled (isStrictRunningOrPaused); 3105 3106 CUSBDeviceVector devsvec = console.GetUSBDevices(); 3107 for (int i = 0; i < devsvec.size(); ++ i) 3108 { 3109 CUSBDevice usb = devsvec [i]; 3110 info += QString ("<br><b><nobr>%1</nobr></b>").arg (vboxGlobal().details (usb)); 3111 } 3112 if (info.isNull()) 3113 info = tr ("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 3114 } 3115 else 3116 { 3117 mDevicesUSBMenu->setEnabled (false); 3118 info = tr ("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 3119 } 3120 3121 mUSBLed->setToolTip (tip.arg (info)); 3122 } 3123 } 3124 if (aElement & VRDPStuff) 3125 { 3126 CVRDPServer vrdpsrv = mSession.GetMachine().GetVRDPServer(); 3127 if (!vrdpsrv.isNull()) 3128 { 3129 /* update menu&status icon state */ 3130 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 3131 mDevicesSwitchVrdpAction->setChecked (isVRDPEnabled); 3132 #if 0 /* TODO: Allow to setup status-bar! */ 3133 mVrdpLed->setState (isVRDPEnabled ? 1 : 0); 3134 3135 QString tip = tr ("Indicates whether the Remote Display (VRDP Server) " 3136 "is enabled (<img src=:/vrdp_16px.png/>) or not " 3137 "(<img src=:/vrdp_disabled_16px.png/>)."); 3138 if (vrdpsrv.GetEnabled()) 3139 tip += tr ("<hr>The VRDP Server is listening on port %1").arg (vrdpsrv.GetPort()); 3140 mVrdpLed->setToolTip (tip); 3141 #endif 3142 } 3143 } 3144 if (aElement & SharedFolderStuff) 3145 { 3146 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3147 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 3148 3149 QString data; 3150 QMap <QString, QString> sfs; 3151 3152 mDevicesSFMenu->setEnabled (true); 3153 3154 /* Permanent folders */ 3155 CSharedFolderVector psfvec = machine.GetSharedFolders(); 3156 3157 for (int i = 0; i < psfvec.size(); ++ i) 3158 { 3159 CSharedFolder sf = psfvec [i]; 3160 sfs.insert (sf.GetName(), sf.GetHostPath()); 3161 } 3162 3163 /* Transient folders */ 3164 CSharedFolderVector tsfvec = console.GetSharedFolders(); 3165 3166 for (int i = 0; i < tsfvec.size(); ++ i) 3167 { 3168 CSharedFolder sf = tsfvec[i]; 3169 sfs.insert (sf.GetName(), sf.GetHostPath()); 3170 } 3171 3172 for (QMap <QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 3173 { 3174 /* Select slashes depending on the OS type */ 3175 if (VBoxGlobal::isDOSType (console.GetGuest().GetOSTypeId())) 3176 data += QString ("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 3177 .arg (it.key(), it.value()); 3178 else 3179 data += QString ("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 3180 .arg (it.key(), it.value()); 3181 } 3182 3183 if (sfs.count() == 0) 3184 data = tr ("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 3185 3186 mSFLed->setToolTip (tip.arg (data)); 3187 } 3188 if (aElement & VirtualizationStuff) 3189 { 3190 bool virtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 3191 QString virtualization = virtEnabled ? 3192 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") : 3193 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)"); 3194 3195 bool nestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 3196 QString nestedPaging = nestEnabled ? 3197 VBoxVMInformationDlg::tr ("Enabled", "nested paging") : 3198 VBoxVMInformationDlg::tr ("Disabled", "nested paging"); 3199 3200 QString tip (tr ("Indicates the status of the hardware virtualization " 3201 "features used by this virtual machine:" 3202 "<br><nobr><b>%1:</b> %2</nobr>" 3203 "<br><nobr><b>%3:</b> %4</nobr>", 3204 "Virtualization Stuff LED") 3205 .arg (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization) 3206 .arg (VBoxVMInformationDlg::tr ("Nested Paging"), nestedPaging)); 3207 3208 int cpuCount = console.GetMachine().GetCPUCount(); 3209 if (cpuCount > 1) 3210 tip += tr ("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 3211 .arg (VBoxGlobal::tr ("Processor(s)", "details report")).arg (cpuCount); 3212 3213 mVirtLed->setToolTip (tip); 3214 mVirtLed->setState (virtEnabled); 3215 } 3216 if (aElement & PauseAction) 3217 { 3218 if (!mVmPauseAction->isChecked()) 3219 { 3220 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Pause"), "P")); 3221 mVmPauseAction->setStatusTip (tr ("Suspend the execution of the virtual machine")); 3222 } 3223 else 3224 { 3225 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("R&esume"), "P")); 3226 mVmPauseAction->setStatusTip (tr ("Resume the execution of the virtual machine" ) ); 3227 } 3228 mVmPauseAction->setEnabled (isRunningOrPaused); 3229 } 3230 if (aElement & DisableMouseIntegrAction) 3231 { 3232 if (!mVmDisableMouseIntegrAction->isChecked()) 3233 { 3234 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Disable &Mouse Integration"), "I")); 3235 mVmDisableMouseIntegrAction->setStatusTip (tr ("Temporarily disable host mouse pointer integration")); 3236 } 3237 else 3238 { 3239 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Enable &Mouse Integration"), "I")); 3240 mVmDisableMouseIntegrAction->setStatusTip (tr ("Enable temporarily disabled host mouse pointer integration")); 3241 } 3242 if ( mMachineState == KMachineState_Running 3243 || mMachineState == KMachineState_Teleporting 3244 || mMachineState == KMachineState_LiveSnapshotting 3245 ) 3246 mVmDisableMouseIntegrAction->setEnabled (mConsole->isMouseAbsolute()); 3247 else 3248 mVmDisableMouseIntegrAction->setEnabled (false); 3249 } 3250 } 3251 3252 /** 3253 * @return @c true if successfully performed the requested operation and false 3254 * otherwise. 3255 */ 3256 bool VBoxConsoleWnd::toggleFullscreenMode (bool aOn, bool aSeamless) 3257 { 3258 /* Please note: For some platforms like the Mac, the calling order of the 3259 * functions in this methods is vital. So please be careful on changing 3260 * this. */ 3261 3262 QSize initialSize = size(); 3263 if (aSeamless || mConsole->isAutoresizeGuestActive()) 3264 { 3265 QRect screen = aSeamless ? 3266 QApplication::desktop()->availableGeometry (this) : 3267 QApplication::desktop()->screenGeometry (this); 3268 ULONG64 availBits = mSession.GetMachine().GetVRAMSize() /* vram */ 3269 * _1M /* mb to bytes */ 3270 * 8; /* to bits */ 3271 ULONG guestBpp = mConsole->console().GetDisplay().GetBitsPerPixel(); 3272 ULONG64 usedBits = (screen.width() /* display width */ 3273 * screen.height() /* display height */ 3274 * guestBpp 3275 + _1M * 8) /* current cache per screen - may be changed in future */ 3276 * mSession.GetMachine().GetMonitorCount() /**< @todo fix assumption that all screens have same resolution */ 3277 + 4096 * 8; /* adapter info */ 3278 if (aOn && (availBits < usedBits)) 3279 { 3280 if (aSeamless) 3281 { 3282 vboxProblem().cannotEnterSeamlessMode ( 3283 screen.width(), screen.height(), guestBpp, 3284 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3285 return false; 3286 } 3287 else 3288 { 3289 int result = vboxProblem().cannotEnterFullscreenMode ( 3290 screen.width(), screen.height(), guestBpp, 3291 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3292 if (result == QIMessageBox::Cancel) 3293 return false; 3294 } 3295 } 3296 } 3297 3298 AssertReturn (mConsole, false); 3299 AssertReturn ((mHiddenChildren.empty() == aOn), false); 3300 AssertReturn ((aSeamless && mIsSeamless != aOn) || 3301 (!aSeamless && mIsFullscreen != aOn), false); 3302 if (aOn) 3303 AssertReturn ((aSeamless && !mIsFullscreen) || 3304 (!aSeamless && !mIsSeamless), false); 3305 3306 if (aOn) 3307 { 3308 /* Take the toggle hot key from the menu item. Since 3309 * VBoxGlobal::extractKeyFromActionText gets exactly the 3310 * linked key without the 'Host+' part we are adding it here. */ 3311 QString hotKey = QString ("Host+%1") 3312 .arg (VBoxGlobal::extractKeyFromActionText (aSeamless ? 3313 mVmSeamlessAction->text() : mVmFullscreenAction->text())); 3314 3315 Assert (!hotKey.isEmpty()); 3316 3317 /* Show the info message. */ 3318 bool ok = aSeamless ? 3319 vboxProblem().confirmGoingSeamless (hotKey) : 3320 vboxProblem().confirmGoingFullscreen (hotKey); 3321 if (!ok) 3322 return false; 3323 } 3324 3325 #ifdef Q_WS_MAC 3326 if (!aSeamless) 3327 { 3328 /* Fade to black */ 3329 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken); 3330 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); 3331 } 3332 #endif 3333 3334 if (aSeamless) 3335 { 3336 /* Activate the auto-resize feature required for the seamless mode. */ 3337 if (!mVmAutoresizeGuestAction->isChecked()) 3338 mVmAutoresizeGuestAction->setChecked (true); 3339 3340 /* Activate the mouse integration feature for the seamless mode. */ 3341 if (mVmDisableMouseIntegrAction->isChecked()) 3342 mVmDisableMouseIntegrAction->setChecked (false); 3343 3344 mVmAdjustWindowAction->setEnabled (!aOn); 3345 mVmFullscreenAction->setEnabled (!aOn); 3346 mVmAutoresizeGuestAction->setEnabled (!aOn); 3347 mVmDisableMouseIntegrAction->setEnabled (!aOn); 3348 3349 mConsole->console().GetDisplay().SetSeamlessMode (aOn); 3350 mIsSeamless = aOn; 3351 } 3352 else 3353 { 3354 mIsFullscreen = aOn; 3355 mVmAdjustWindowAction->setEnabled (!aOn); 3356 mVmSeamlessAction->setEnabled (!aOn && mIsSeamlessSupported && mIsGraphicsSupported); 3357 } 3358 3359 bool wasHidden = isHidden(); 3360 3361 /* Temporarily disable the mode-related action to make sure 3362 * user can not leave the mode before he enter it and inside out. */ 3363 aSeamless ? mVmSeamlessAction->setEnabled (false) : 3364 mVmFullscreenAction->setEnabled (false); 3365 3366 /* Calculate initial console size */ 3367 QSize consoleSize; 3368 3369 if (aOn) 3370 { 3371 consoleSize = mConsole->frameSize(); 3372 consoleSize -= QSize (mConsole->frameWidth() * 2, mConsole->frameWidth() * 2); 3373 3374 /* Toggle console to manual resize mode. */ 3375 mConsole->setIgnoreMainwndResize (true); 3376 3377 /* Memorize the maximized state. */ 3378 QDesktopWidget *dtw = QApplication::desktop(); 3379 mWasMax = isWindowMaximized() && 3380 dtw->availableGeometry().width() == frameSize().width() && 3381 dtw->availableGeometry().height() == frameSize().height(); 3382 3383 /* Save the previous scroll-view minimum size before entering 3384 * fullscreen/seamless state to restore this minimum size before 3385 * the exiting fullscreen. Required for correct scroll-view and 3386 * guest display update in SDL mode. */ 3387 mPrevMinSize = mConsole->minimumSize(); 3388 mConsole->setMinimumSize (0, 0); 3389 3390 /* let the widget take the whole available desktop space */ 3391 QRect scrGeo = aSeamless ? 3392 dtw->availableGeometry (this) : dtw->screenGeometry (this); 3393 3394 /* It isn't guaranteed that the guest os set the video mode that 3395 * we requested. So after all the resizing stuff set the clipping 3396 * mask and the spacing shifter to the corresponding values. */ 3397 if (aSeamless) 3398 setViewInSeamlessMode (scrGeo); 3399 3400 #ifdef Q_WS_WIN 3401 mPrevRegion = dtw->screenGeometry (this); 3402 #endif 3403 3404 /* Hide all but the central widget containing the console view. */ 3405 QList <QWidget*> list (findChildren <QWidget*> ()); 3406 QList <QWidget*> excludes; 3407 excludes << centralWidget() << centralWidget()->findChildren <QWidget*> (); 3408 foreach (QWidget *w, list) 3409 { 3410 if (!excludes.contains (w)) 3411 { 3412 if (!w->isHidden()) 3413 { 3414 w->hide(); 3415 mHiddenChildren.append (w); 3416 } 3417 } 3418 } 3419 3420 /* Adjust colors and appearance. */ 3421 mErasePalette = centralWidget()->palette(); 3422 QPalette palette(mErasePalette); 3423 palette.setColor (centralWidget()->backgroundRole(), Qt::black); 3424 centralWidget()->setPalette (palette); 3425 centralWidget()->setAutoFillBackground (!aSeamless); 3426 mConsoleStyle = mConsole->frameStyle(); 3427 mConsole->setFrameStyle (QFrame::NoFrame); 3428 mConsole->setMaximumSize (scrGeo.size()); 3429 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3430 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3431 } 3432 else 3433 { 3434 /* Reset the shifting spacers. */ 3435 mShiftingSpacerLeft->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3436 mShiftingSpacerTop->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3437 mShiftingSpacerRight->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3438 mShiftingSpacerBottom->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3439 3440 /* Restore the previous scroll-view minimum size before the exiting 3441 * fullscreen. Required for correct scroll-view and guest display 3442 * update in SDL mode. */ 3443 mConsole->setMinimumSize (mPrevMinSize); 3444 3445 #ifdef Q_WS_MAC 3446 if (aSeamless) 3447 { 3448 /* Please note: All the stuff below has to be done before the 3449 * window switch back to normal size. Qt changes the winId on the 3450 * fullscreen switch and make this stuff useless with the old 3451 * winId. So please be careful on rearrangement of the method 3452 * calls. */ 3453 /* Undo all mac specific installations */ 3454 ::darwinSetShowsWindowTransparent (this, false); 3455 } 3456 #endif 3457 3458 /* Adjust colors and appearance. */ 3459 clearMask(); 3460 centralWidget()->setPalette (mErasePalette); 3461 centralWidget()->setAutoFillBackground (false); 3462 mConsole->setFrameStyle (mConsoleStyle); 3463 mConsole->setMaximumSize (mConsole->sizeHint()); 3464 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3465 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3466 3467 /* Show everything hidden when going fullscreen. */ 3468 foreach (QPointer <QWidget> child, mHiddenChildren) 3469 if (child) child->show(); 3470 mHiddenChildren.clear(); 3471 } 3472 3473 /* Set flag for waiting host resize if it awaited during mode entering */ 3474 if ((mIsFullscreen || mIsSeamless) && (consoleSize != initialSize)) 3475 mIsWaitingModeResize = true; 3476 3477 if (!aOn) 3478 { 3479 /* Animation takes a bit long, the mini toolbar is still disappearing 3480 * when switched to normal mode so hide it completely */ 3481 mMiniToolBar->hide(); 3482 mMiniToolBar->updateDisplay (false, true); 3483 } 3484 3485 /* Toggle qt full-screen mode */ 3486 switchToFullscreen (aOn, aSeamless); 3487 3488 if (aOn) 3489 { 3490 mMiniToolBar->setSeamlessMode (aSeamless); 3491 mMiniToolBar->updateDisplay (true, true); 3492 } 3493 3494 #ifdef Q_WS_MAC 3495 if (aOn && aSeamless) 3496 { 3497 /* Please note: All the stuff below has to be done after the window has 3498 * switched to fullscreen. Qt changes the winId on the fullscreen 3499 * switch and make this stuff useless with the old winId. So please be 3500 * careful on rearrangement of the method calls. */ 3501 ::darwinSetShowsWindowTransparent (this, true); 3502 } 3503 #endif 3504 3505 /* Send guest size hint */ 3506 mConsole->toggleFSMode (consoleSize); 3507 3508 /* Process all console attributes changes and sub-widget hidings */ 3509 qApp->processEvents(); 3510 3511 if (!mIsWaitingModeResize) 3512 onExitFullscreen(); 3513 3514 /* Unlock FS actions locked during modes toggling */ 3515 QTimer::singleShot (300, this, SLOT (unlockActionsSwitch())); 3516 3517 #ifdef Q_WS_MAC /* wasHidden is wrong on the mac it seems. */ 3518 /** @todo figure out what is really wrong here... */ 3519 if (!wasHidden) 3520 show(); 3521 #else 3522 if (wasHidden) 3523 hide(); 3524 #endif 3525 3526 return true; 3527 } 3528 3529 void VBoxConsoleWnd::switchToFullscreen (bool aOn, bool aSeamless) 3530 { 3531 #ifdef Q_WS_MAC 3532 # ifndef QT_MAC_USE_COCOA 3533 /* setWindowState removes the window group connection somehow. So save it 3534 * temporary. */ 3535 WindowGroupRef g = GetWindowGroup (::darwinToNativeWindow (this)); 3536 # endif /* !QT_MAC_USE_COCOA */ 3537 if (aSeamless) 3538 if (aOn) 3539 { 3540 /* Save for later restoring */ 3541 mNormalGeometry = geometry(); 3542 mSavedFlags = windowFlags(); 3543 /* Remove the frame from the window */ 3544 const QRect fullscreen (qApp->desktop()->screenGeometry (qApp->desktop()->screenNumber (this))); 3545 setParent (0, Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); 3546 setGeometry (fullscreen); 3547 /* Set it maximized */ 3548 setWindowState (windowState() ^ Qt::WindowMaximized); 3549 } 3550 else 3551 { 3552 /* Restore old values */ 3553 setParent (0, mSavedFlags); 3554 setGeometry (mNormalGeometry); 3555 } 3556 else 3557 { 3558 /* Here we are going really fullscreen */ 3559 setWindowState (windowState() ^ Qt::WindowFullScreen); 3560 changePresentationMode (VBoxChangePresentationModeEvent(aOn)); 3561 } 3562 3563 # ifndef QT_MAC_USE_COCOA 3564 /* Reassign the correct window group. */ 3565 SetWindowGroup (::darwinToNativeWindow (this), g); 3566 # endif /* !QT_MAC_USE_COCOA */ 3567 #else 3568 NOREF (aOn); 3569 NOREF (aSeamless); 3570 setWindowState (windowState() ^ Qt::WindowFullScreen); 3571 #endif 3572 } 3573 3574 void VBoxConsoleWnd::setViewInSeamlessMode (const QRect &aTargetRect) 3575 { 3576 #ifndef Q_WS_MAC 3577 /* It isn't guaranteed that the guest os set the video mode that 3578 * we requested. So after all the resizing stuff set the clipping 3579 * mask and the spacing shifter to the corresponding values. */ 3580 QDesktopWidget *dtw = QApplication::desktop(); 3581 QRect sRect = dtw->screenGeometry (this); 3582 QRect aRect (aTargetRect); 3583 mMaskShift.scale (aTargetRect.left(), aTargetRect.top(), Qt::IgnoreAspectRatio); 3584 /* Set the clipping mask */ 3585 mStrictedRegion = aRect; 3586 /* Set the shifting spacer */ 3587 mShiftingSpacerLeft->changeSize (RT_ABS (sRect.left() - aRect.left()), 0, 3588 QSizePolicy::Fixed, QSizePolicy::Preferred); 3589 mShiftingSpacerTop->changeSize (0, RT_ABS (sRect.top() - aRect.top()), 3590 QSizePolicy::Preferred, QSizePolicy::Fixed); 3591 mShiftingSpacerRight->changeSize (RT_ABS (sRect.right() - aRect.right()), 0, 3592 QSizePolicy::Fixed, QSizePolicy::Preferred); 3593 mShiftingSpacerBottom->changeSize (0, RT_ABS (sRect.bottom() - aRect.bottom()), 3594 QSizePolicy::Preferred, QSizePolicy::Fixed); 3595 #else // !Q_WS_MAC 3596 NOREF (aTargetRect); 3597 #endif // !Q_WS_MAC 3598 } 3599 3600 /** 3601 * Closes the console view opened by openView(). 3602 * Does nothing if no console view was opened. 3603 */ 3604 void VBoxConsoleWnd::closeView() 3605 { 3606 LogFlowFuncEnter(); 3607 3608 if (!mConsole) 3609 { 3610 LogFlow (("Already closed!\n")); 3611 LogFlowFuncLeave(); 3612 return; 3613 } 3614 3615 mConsole->detach(); 3616 centralWidget()->layout()->removeWidget (mConsole); 3617 delete mConsole; 3618 mConsole = 0; 3619 mSession.Close(); 3620 mSession.detach(); 3621 3622 LogFlowFuncLeave(); 3623 } 3624 3625 #ifdef VBOX_WITH_DEBUGGER_GUI 3626 3627 /** 3628 * Prepare the Debug menu. 3629 */ 3630 void VBoxConsoleWnd::dbgPrepareDebugMenu() 3631 { 3632 /* The "Logging" item. */ 3633 bool fEnabled = false; 3634 bool fChecked = false; 3635 CConsole console = mSession.GetConsole(); 3636 if (console.isOk()) 3637 { 3638 CMachineDebugger cdebugger = console.GetDebugger(); 3639 if (console.isOk()) 3640 { 3641 fEnabled = true; 3642 fChecked = cdebugger.GetLogEnabled() != FALSE; 3643 } 3644 } 3645 if (fEnabled != mDbgLoggingAction->isEnabled()) 3646 mDbgLoggingAction->setEnabled (fEnabled); 3647 if (fChecked != mDbgLoggingAction->isChecked()) 3648 mDbgLoggingAction->setChecked (fChecked); 3649 } 3650 3651 /** 3652 * Called when the Debug->Statistics... menu item is selected. 3653 */ 3654 void VBoxConsoleWnd::dbgShowStatistics() 3655 { 3656 if (dbgCreated()) 3657 mDbgGuiVT->pfnShowStatistics (mDbgGui); 3658 } 3659 3660 /** 3661 * Called when the Debug->Command Line... menu item is selected. 3662 */ 3663 void VBoxConsoleWnd::dbgShowCommandLine() 3664 { 3665 if (dbgCreated()) 3666 mDbgGuiVT->pfnShowCommandLine (mDbgGui); 3667 } 3668 3669 /** 3670 * Called when the Debug->Logging menu item is selected. 3671 */ 3672 void VBoxConsoleWnd::dbgLoggingToggled (bool aState) 3673 { 3674 NOREF(aState); 3675 CConsole console = mSession.GetConsole(); 3676 if (console.isOk()) 3677 { 3678 CMachineDebugger cdebugger = console.GetDebugger(); 3679 if (console.isOk()) 3680 cdebugger.SetLogEnabled (aState); 3681 } 3682 } 3683 3684 /** 3685 * Ensures that the debugger GUI instance is ready. 3686 * 3687 * @returns true if instance is fine and dandy. 3688 * @returns flase if it's not. 3689 */ 3690 bool VBoxConsoleWnd::dbgCreated() 3691 { 3692 if (mDbgGui) 3693 return true; 3694 3695 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 3696 if (hLdrMod == NIL_RTLDRMOD) 3697 return false; 3698 3699 PFNDBGGUICREATE pfnGuiCreate; 3700 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 3701 if (RT_SUCCESS (rc)) 3702 { 3703 ISession *pISession = mSession.raw(); 3704 rc = pfnGuiCreate (pISession, &mDbgGui, &mDbgGuiVT); 3705 if (RT_SUCCESS (rc)) 3706 { 3707 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (mDbgGuiVT->u32Version, DBGGUIVT_VERSION) || 3708 mDbgGuiVT->u32EndVersion == mDbgGuiVT->u32Version) 3709 { 3710 mDbgGuiVT->pfnSetParent (mDbgGui, (QWidget*) this); 3711 mDbgGuiVT->pfnSetMenu (mDbgGui, (QMenu*) mDbgMenu); 3712 dbgAdjustRelativePos(); 3713 return true; 3714 } 3715 3716 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 3717 mDbgGuiVT->u32Version, mDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3718 } 3719 else 3720 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 3721 } 3722 else 3723 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 3724 3725 mDbgGui = 0; 3726 mDbgGuiVT = 0; 3727 return false; 3728 } 3729 3730 /** 3731 * Destroys the debugger GUI instacne if it has been created. 3732 */ 3733 void VBoxConsoleWnd::dbgDestroy() 3734 { 3735 if (mDbgGui) 3736 { 3737 mDbgGuiVT->pfnDestroy (mDbgGui); 3738 mDbgGui = 0; 3739 mDbgGuiVT = 0; 3740 } 3741 } 3742 3743 /** 3744 * Tells the debugger GUI that the console window has moved or been resized. 3745 */ 3746 void VBoxConsoleWnd::dbgAdjustRelativePos() 3747 { 3748 if (mDbgGui) 3749 { 3750 QRect rct = frameGeometry(); 3751 mDbgGuiVT->pfnAdjustRelativePos (mDbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 3752 } 3753 } 3754 3755 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3756 3757 VBoxNetworkDialog::VBoxNetworkDialog (QWidget *aParent, CSession &aSession) 3758 : QIWithRetranslateUI <QDialog> (aParent) 3759 , mSettings (0) 3760 , mSession (aSession) 3761 { 3762 setModal (true); 3763 /* Setup Dialog's options */ 3764 setWindowIcon (QIcon (":/nw_16px.png")); 3765 setSizeGripEnabled (true); 3766 3767 /* Setup main dialog's layout */ 3768 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3769 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3770 mainLayout->setSpacing (10); 3771 3772 /* Setup settings layout */ 3773 mSettings = new VBoxVMSettingsNetworkPage (true); 3774 mSettings->setOrderAfter (this); 3775 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3776 mSettings->getFrom (aSession.GetMachine()); 3777 mainLayout->addWidget (mSettings); 3778 3779 /* Setup button's layout */ 3780 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3781 3782 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3783 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3784 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3785 mainLayout->addWidget (buttonBox); 3786 3787 retranslateUi(); 3788 } 3789 3790 void VBoxNetworkDialog::retranslateUi() 3791 { 3792 setWindowTitle (tr ("Network Adapters")); 3793 } 3794 3795 void VBoxNetworkDialog::accept() 3796 { 3797 mSettings->putBackTo(); 3798 CMachine machine = mSession.GetMachine(); 3799 machine.SaveSettings(); 3800 if (!machine.isOk()) 3801 vboxProblem().cannotSaveMachineSettings (machine); 3802 QDialog::accept(); 3803 } 3804 3805 void VBoxNetworkDialog::showEvent (QShowEvent *aEvent) 3806 { 3807 resize (450, 300); 3808 VBoxGlobal::centerWidget (this, parentWidget()); 3809 setMinimumWidth (400); 3810 QDialog::showEvent (aEvent); 3811 } 3812 3813 VBoxSFDialog::VBoxSFDialog (QWidget *aParent, CSession &aSession) 3814 : QIWithRetranslateUI <QDialog> (aParent) 3815 , mSettings (0) 3816 , mSession (aSession) 3817 { 3818 setModal (true); 3819 /* Setup Dialog's options */ 3820 setWindowIcon (QIcon (":/select_file_16px.png")); 3821 setSizeGripEnabled (true); 3822 3823 /* Setup main dialog's layout */ 3824 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3825 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3826 mainLayout->setSpacing (10); 3827 3828 /* Setup settings layout */ 3829 mSettings = new VBoxVMSettingsSF (MachineType | ConsoleType, this); 3830 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3831 mSettings->getFromConsole (aSession.GetConsole()); 3832 mSettings->getFromMachine (aSession.GetMachine()); 3833 mainLayout->addWidget (mSettings); 3834 3835 /* Setup button's layout */ 3836 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3837 3838 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3839 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3840 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3841 mainLayout->addWidget (buttonBox); 3842 3843 retranslateUi(); 3844 } 3845 3846 void VBoxSFDialog::retranslateUi() 3847 { 3848 setWindowTitle (tr ("Shared Folders")); 3849 } 3850 3851 void VBoxSFDialog::accept() 3852 { 3853 mSettings->putBackToConsole(); 3854 mSettings->putBackToMachine(); 3855 CMachine machine = mSession.GetMachine(); 3856 machine.SaveSettings(); 3857 if (!machine.isOk()) 3858 vboxProblem().cannotSaveMachineSettings (machine); 3859 QDialog::accept(); 3860 } 3861 3862 void VBoxSFDialog::showEvent (QShowEvent *aEvent) 3863 { 3864 resize (450, 300); 3865 VBoxGlobal::centerWidget (this, parentWidget()); 3866 setMinimumWidth (400); 3867 QDialog::showEvent (aEvent); 3868 } 3869 3870 #include "VBoxConsoleWnd.moc" 200 #include "UIMachine.moc" -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass declaration4 * UIMachine class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2009Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef __VBoxConsoleWnd_h__ 24 #define __VBoxConsoleWnd_h__ 25 26 /* Global includes */ 27 #include <QColor> 28 #include <QDialog> 29 #include <QMainWindow> 30 #include <QMap> 31 #include <QMenu> 32 #include <QPointer> 23 #ifndef __UIMachine_h__ 24 #define __UIMachine_h__ 33 25 34 26 /* Local includes */ 35 27 #include "COMDefs.h" 36 #include "QIWithRetranslateUI.h" 37 #include "VBoxProblemReporter.h" 38 #include "VBoxHelpActions.h" 39 40 #ifdef VBOX_WITH_DEBUGGER_GUI 41 # include <VBox/dbggui.h> 42 #endif 43 #ifdef Q_WS_MAC 44 # include <ApplicationServices/ApplicationServices.h> 45 # ifndef QT_MAC_USE_COCOA 46 # include <Carbon/Carbon.h> 47 # endif /* !QT_MAC_USE_COCOA */ 48 #endif 49 50 /* Global forwards */ 51 class QAction; 52 class QActionGroup; 53 class QLabel; 54 class QSpacerItem; 55 class QIWidgetValidator; 28 #include "UIMachineDefs.h" 56 29 57 30 /* Local forwards */ 58 class QIMenu; 59 class QIStateIndicator; 60 class VBoxChangeDockIconUpdateEvent; 61 class VBoxChangePresentationModeEvent; 62 class VBoxConsoleView; 63 class VBoxMiniToolBar; 64 class VBoxSwitchMenu; 65 class VBoxUSBMenu; 31 class UIActionsPool; 32 class UIVisualState; 66 33 67 class VBoxConsoleWnd : public QIWithRetranslateUI2 <QMainWindow>34 class UIMachine : public QObject 68 35 { 69 36 Q_OBJECT; … … 71 38 public: 72 39 73 VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent = 0, Qt::WindowFlags aFlags = Qt::Window); 74 virtual ~VBoxConsoleWnd(); 75 76 bool isWindowMaximized() const 77 { 78 #ifdef Q_WS_MAC 79 /* On Mac OS X we didn't really jump to the fullscreen mode but 80 * maximize the window. This situation has to be considered when 81 * checking for maximized or fullscreen mode. */ 82 return !isTrueSeamless() && QMainWindow::isMaximized(); 83 #else /* Q_WS_MAC */ 84 return QMainWindow::isMaximized(); 85 #endif /* Q_WS_MAC */ 86 } 87 bool isWindowFullScreen() const 88 { 89 #ifdef Q_WS_MAC 90 /* On Mac OS X we didn't really jump to the fullscreen mode but 91 * maximize the window. This situation has to be considered when 92 * checking for maximized or fullscreen mode. */ 93 return isTrueFullscreen() || isTrueSeamless(); 94 #else /* Q_WS_MAC */ 95 return QMainWindow::isFullScreen(); 96 #endif /* Q_WS_MAC */ 97 } 98 bool isTrueFullscreen() const { return mIsFullscreen; } 99 bool isTrueSeamless() const { return mIsSeamless; } 100 101 KMachineState machineState() const { return mMachineState; } 102 103 bool openView (const CSession &aSession); 104 105 void setMouseIntegrationLocked (bool aDisabled); 106 107 void popupMainMenu (bool aCenter); 108 109 void installGuestAdditionsFrom (const QString &aSource); 110 111 void setMask (const QRegion &aRegion); 112 void clearMask(); 113 114 /* informs that the guest display is resized */ 115 void onDisplayResize (ulong aHeight, ulong aWidth); 116 117 #ifdef VBOX_WITH_VIDEOHWACCEL 118 /* used for obtaining the extradata settings */ 119 CSession &session() { return mSession; } 120 #endif 121 signals: 122 123 void closing(); 124 125 protected: 126 127 bool event (QEvent *aEvent); 128 void closeEvent (QCloseEvent *aEvent); 129 #ifdef Q_WS_X11 130 bool x11Event (XEvent *aEvent); 131 #endif 132 133 void retranslateUi(); 40 UIMachine(UIMachine **ppSelf, const CSession &session); 134 41 135 42 private slots: 136 43 137 void finalizeOpenView(); 138 void tryClose(); 139 140 void vmFullscreen (bool aOn); 141 void vmSeamless (bool aOn); 142 void vmAutoresizeGuest (bool aOn); 143 void vmAdjustWindow(); 144 void vmDisableMouseIntegration (bool aOff); 145 void vmTypeCAD(); 146 #ifdef Q_WS_X11 147 void vmTypeCABS(); 148 #endif 149 void vmTakeSnapshot(); 150 void vmShowInfoDialog(); 151 void vmReset(); 152 void vmPause (bool aOn); 153 void vmACPIShutdown(); 154 void vmClose(); 155 156 void devicesSwitchVrdp (bool aOn); 157 void devicesOpenNetworkDialog(); 158 void devicesOpenSFDialog(); 159 void devicesInstallGuestAdditions(); 160 161 void prepareStorageMenu(); 162 void prepareNetworkMenu(); 163 void prepareSFMenu(); 164 165 void mountMedium(); 166 void switchUSB (QAction *aAction); 167 168 void showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent); 169 170 void updateDeviceLights(); 171 void updateMachineState (KMachineState aState); 172 void updateMouseState (int aState); 173 void updateAdditionsState (const QString &aVersion, bool aActive, 174 bool aSeamlessSupported, bool aGraphicsSupported); 175 void updateNetworkAdaptersState(); 176 void updateUsbState(); 177 void updateMediaDriveState (VBoxDefs::MediumType aType); 178 void updateSharedFoldersState(); 179 180 void onExitFullscreen(); 181 void unlockActionsSwitch(); 182 183 void mtExitMode(); 184 void mtCloseVM(); 185 void mtMaskUpdate(); 186 187 void changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent); 188 void changePresentationMode (const VBoxChangePresentationModeEvent &aEvent); 189 void processGlobalSettingChange (const char *aPublicName, const char *aName); 190 191 #ifdef VBOX_WITH_DEBUGGER_GUI 192 void dbgPrepareDebugMenu(); 193 void dbgShowStatistics(); 194 void dbgShowCommandLine(); 195 void dbgLoggingToggled (bool aBool); 196 #endif 44 void sltChangeVisualState(UIVisualStateType visualStateType); 197 45 198 46 private: 199 47 200 enum /* Stuff */ 201 { 202 HardDiskStuff = 0x01, 203 DVDStuff = 0x02, 204 FloppyStuff = 0x04, 205 PauseAction = 0x08, 206 NetworkStuff = 0x10, 207 DisableMouseIntegrAction = 0x20, 208 Caption = 0x40, 209 USBStuff = 0x80, 210 VRDPStuff = 0x100, 211 SharedFolderStuff = 0x200, 212 VirtualizationStuff = 0x400, 213 AllStuff = 0xFFFF, 214 }; 48 void enterBaseVisualState(); 215 49 216 void checkRequiredFeatures(); 217 void activateUICustomizations(); 218 219 void updateAppearanceOf (int aElement); 220 221 bool toggleFullscreenMode (bool aOn, bool aSeamless); 222 void switchToFullscreen (bool aOn, bool aSeamless); 223 void setViewInSeamlessMode (const QRect &aTargetRect); 224 225 void closeView(); 226 227 #ifdef VBOX_WITH_DEBUGGER_GUI 228 bool dbgCreated(); 229 void dbgDestroy(); 230 void dbgAdjustRelativePos(); 231 #endif 232 233 /* COM Variables */ 234 CSession mSession; 235 236 /* Machine State */ 237 KMachineState mMachineState; 238 239 /* Window Variables */ 240 QString mCaptionPrefix; 241 int mConsoleStyle; 242 243 /* Menu items */ 244 QIMenu *mMainMenu; 245 QMenu *mVMMenu; 246 QMenu *mVMMenuMini; 247 QMenu *mDevicesMenu; 248 QMenu *mDevicesCDMenu; 249 QMenu *mDevicesFDMenu; 250 QMenu *mDevicesNetworkMenu; 251 QMenu *mDevicesSFMenu; 252 VBoxUSBMenu *mDevicesUSBMenu; 253 VBoxSwitchMenu *mVmDisMouseIntegrMenu; 254 #if 0 /* todo: allow to setup */ 255 VBoxSwitchMenu *mDevicesVRDPMenu; 256 VBoxSwitchMenu *mVmAutoresizeMenu; 257 #endif 258 #ifdef VBOX_WITH_DEBUGGER_GUI 259 QMenu *mDbgMenu; 260 #endif 261 QMenu *mHelpMenu; 262 263 QActionGroup *mRunningActions; 264 QActionGroup *mRunningOrPausedActions; 265 266 /* Machine actions */ 267 QAction *mVmFullscreenAction; 268 QAction *mVmSeamlessAction; 269 QAction *mVmAutoresizeGuestAction; 270 QAction *mVmAdjustWindowAction; 271 QAction *mVmDisableMouseIntegrAction; 272 QAction *mVmTypeCADAction; 273 #ifdef Q_WS_X11 274 QAction *mVmTypeCABSAction; 275 #endif 276 QAction *mVmTakeSnapshotAction; 277 QAction *mVmShowInformationDlgAction; 278 QAction *mVmResetAction; 279 QAction *mVmPauseAction; 280 QAction *mVmACPIShutdownAction; 281 QAction *mVmCloseAction; 282 283 /* Devices actions */ 284 QAction *mDevicesNetworkDialogAction; 285 QAction *mDevicesSFDialogAction; 286 QAction *mDevicesSwitchVrdpSeparator; 287 QAction *mDevicesSwitchVrdpAction; 288 QAction *mDevicesInstallGuestToolsAction; 289 290 #ifdef VBOX_WITH_DEBUGGER_GUI 291 /* Debugger actions */ 292 QAction *mDbgStatisticsAction; 293 QAction *mDbgCommandLineAction; 294 QAction *mDbgLoggingAction; 295 #endif 296 297 /* Help actions */ 298 VBoxHelpActions mHelpActions; 299 300 /* Widgets */ 301 VBoxConsoleView *mConsole; 302 VBoxMiniToolBar *mMiniToolBar; 303 #ifdef VBOX_WITH_DEBUGGER_GUI 304 /** The handle to the debugger gui. */ 305 PDBGGUI mDbgGui; 306 /** The virtual method table for the debugger GUI. */ 307 PCDBGGUIVT mDbgGuiVT; 308 #endif 309 310 /* Timer to update LEDs */ 311 QTimer *mIdleTimer; 312 313 /* LEDs */ 314 QIStateIndicator *mHDLed; 315 QIStateIndicator *mCDLed; 316 #if 0 /* todo: allow to setup */ 317 QIStateIndicator *mFDLed; 318 #endif 319 QIStateIndicator *mNetLed; 320 QIStateIndicator *mUSBLed; 321 QIStateIndicator *mSFLed; 322 QIStateIndicator *mVirtLed; 323 QIStateIndicator *mMouseLed; 324 QIStateIndicator *mHostkeyLed; 325 QWidget *mHostkeyLedContainer; 326 QLabel *mHostkeyName; 327 #if 0 /* todo: allow to setup */ 328 QIStateIndicator *mVrdpLed; 329 QIStateIndicator *mAutoresizeLed; 330 #endif 331 332 /* Normal Mode */ 333 QRect mNormalGeo; 334 335 /* Fullscreen/Seamless Mode */ 336 QList < QPointer <QWidget> > mHiddenChildren; 337 QSpacerItem *mShiftingSpacerLeft; 338 QSpacerItem *mShiftingSpacerTop; 339 QSpacerItem *mShiftingSpacerRight; 340 QSpacerItem *mShiftingSpacerBottom; 341 QPalette mErasePalette; 342 QSize mPrevMinSize; 343 QSize mMaskShift; 344 QRegion mStrictedRegion; 345 #ifdef Q_WS_WIN 346 QRegion mPrevRegion; 347 #endif 348 #ifdef Q_WS_MAC 349 //QRegion mCurrRegion; 350 # ifndef QT_MAC_USE_COCOA 351 //EventHandlerRef mDarwinRegionEventHandlerRef; 352 # endif 353 /* For seamless maximizing */ 354 QRect mNormalGeometry; 355 Qt::WindowFlags mSavedFlags; 356 /* For the fade effect if the the window goes fullscreen */ 357 CGDisplayFadeReservationToken mFadeToken; 358 #endif 359 360 /* Different bool flags */ 361 bool mIsOpenViewFinished : 1; 362 bool mIsFirstTimeStarted : 1; 363 bool mIsAutoSaveMedia : 1; 364 bool mNoAutoClose : 1; 365 bool mIsFullscreen : 1; 366 bool mIsSeamless : 1; 367 bool mIsSeamlessSupported : 1; 368 bool mIsGraphicsSupported : 1; 369 bool mIsWaitingModeResize : 1; 370 bool mWasMax : 1; 50 CSession m_session; 51 UIActionsPool *m_pActionsPool; 52 UIVisualState *m_pVisualState; 371 53 }; 372 54 373 /* We want to make the first action highlighted but not 374 * selected, but Qt makes the both or neither one of this, 375 * so, just move the focus to the next eligible object, 376 * which will be the first menu action. This little 377 * subclass made only for that purpose. */ 378 class QIMenu : public QMenu 379 { 380 Q_OBJECT; 381 382 public: 383 384 QIMenu (QWidget *aParent) : QMenu (aParent) {} 385 386 void selectFirstAction() { QMenu::focusNextChild(); } 387 }; 388 389 class VBoxSettingsPage; 390 class VBoxNetworkDialog : public QIWithRetranslateUI <QDialog> 391 { 392 Q_OBJECT; 393 394 public: 395 396 VBoxNetworkDialog (QWidget *aParent, CSession &aSession); 397 398 protected: 399 400 void retranslateUi(); 401 402 protected slots: 403 404 virtual void accept(); 405 406 protected: 407 408 void showEvent (QShowEvent *aEvent); 409 410 private: 411 412 VBoxSettingsPage *mSettings; 413 CSession &mSession; 414 }; 415 416 class VBoxVMSettingsSF; 417 class VBoxSFDialog : public QIWithRetranslateUI <QDialog> 418 { 419 Q_OBJECT; 420 421 public: 422 423 VBoxSFDialog (QWidget *aParent, CSession &aSession); 424 425 protected: 426 427 void retranslateUi(); 428 429 protected slots: 430 431 virtual void accept(); 432 433 protected: 434 435 void showEvent (QShowEvent *aEvent); 436 437 private: 438 439 VBoxVMSettingsSF *mSettings; 440 CSession &mSession; 441 }; 442 443 #endif // __VBoxConsoleWnd_h__ 55 #endif // __UIMachine_h__ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass implementation4 * UIMachineLogic class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010 Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 23 23 /* Global includes */ 24 #ifdef VBOX_WITH_PRECOMPILED_HEADERS25 # include "precomp.h"26 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */27 #include <QActionGroup>28 #include <QDesktopWidget>29 24 #include <QDir> 30 25 #include <QFileInfo> 31 #include <QMenuBar>32 26 #include <QProgressBar> 33 #include <QTimer> 27 #include <QDesktopWidget> 28 29 /* Local includes */ 30 #include "VBoxGlobal.h" 31 #include "VBoxProblemReporter.h" 32 33 #include "VBoxMediaManagerDlg.h" 34 #include "VBoxTakeSnapshotDlg.h" 35 #include "VBoxVMInformationDlg.h" 36 #include "VBoxVMSettingsNetwork.h" 37 #include "VBoxVMSettingsSF.h" 38 //#include "VBoxDownloaderWgt.h" 39 40 #include "QIFileDialog.h" 41 #include "QIHttp.h" 42 43 #include "UIActionsPool.h" 44 #include "UIMachineLogic.h" 45 #include "UIMachineLogicNormal.h" 46 //#include "UIMachineLogicFullscreen.h" 47 //#include "UIMachineLogicSeamless.h" 48 #include "UIMachineWindow.h" 49 #include "UIMachineView.h" 50 51 #include <iprt/param.h> 52 #include <iprt/path.h> 53 #include <VBox/VMMDev.h> 54 55 #ifdef VBOX_WITH_DEBUGGER_GUI 56 # include <iprt/ldr.h> 57 #endif 58 59 #ifdef Q_WS_X11 60 # include <XKeyboard.h> 61 #endif 34 62 35 63 #ifdef Q_WS_X11 36 64 # include <QX11Info> 37 65 #endif 38 #ifdef Q_WS_MAC 39 # include <QPainter> 40 #endif 41 42 /* Local includes */ 43 #include "QIFileDialog.h" 44 #include "QIHotKeyEdit.h" 45 #include "QIHttp.h" 46 #include "QIStateIndicator.h" 47 #include "QIStatusBar.h" 48 #include "QIWidgetValidator.h" 49 #include "QIHotKeyEdit.h" 50 #include "VBoxConsoleWnd.h" 51 #include "VBoxConsoleView.h" 52 #include "VBoxCloseVMDlg.h" 53 #include "VBoxDownloaderWgt.h" 54 #include "VBoxGlobal.h" 55 #include "VBoxMediaManagerDlg.h" 56 #include "VBoxMiniToolBar.h" 57 #include "VBoxProblemReporter.h" 58 #include "VBoxTakeSnapshotDlg.h" 59 #include "UIFirstRunWzd.h" 60 #include "VBoxVMSettingsNetwork.h" 61 #include "VBoxVMSettingsSF.h" 62 #include "VBoxVMInformationDlg.h" 63 64 #ifdef Q_WS_X11 65 # include <X11/Xlib.h> 66 # include <XKeyboard.h> 67 #endif 68 #ifdef Q_WS_MAC 69 # include "VBoxUtils.h" 70 # include "VBoxIChatTheaterWrapper.h" 71 # include <ApplicationServices/ApplicationServices.h> 72 #endif 73 #ifdef VBOX_WITH_DEBUGGER_GUI 74 # include <VBox/err.h> 75 # include <iprt/ldr.h> 76 #endif 77 78 #include <VBox/VMMDev.h> /** @todo @bugref{4084} */ 79 #include <iprt/buildconfig.h> 80 #include <iprt/param.h> 81 #include <iprt/path.h> 82 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 83 84 /* Global forwards */ 85 extern void qt_set_sequence_auto_mnemonic (bool on); 86 87 /** class StatusTipEvent 88 * 89 * The StatusTipEvent class is an auxiliary QEvent class 90 * for carrying statusTip text of non-QAction menu item's. 91 * This event is posted then the menu item is highlighted but 92 * processed later in VBoxConsoleWnd::event() handler to 93 * avoid statusBar messaging collisions. 94 */ 95 class StatusTipEvent : public QEvent 96 { 66 67 struct MountTarget 68 { 69 MountTarget() : name(QString("")), port(0), device(0), id(QString()), type(VBoxDefs::MediumType_Invalid) {} 70 MountTarget(const QString &strName, LONG iPort, LONG iDevice) 71 : name(strName), port(iPort), device(iDevice), id(QString()), type(VBoxDefs::MediumType_Invalid) {} 72 MountTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strId) 73 : name(strName), port(iPort), device(iDevice), id(strId), type(VBoxDefs::MediumType_Invalid) {} 74 MountTarget(const QString &strName, LONG iPort, LONG iDevice, VBoxDefs::MediumType eType) 75 : name(strName), port(iPort), device(iDevice), id(QString()), type(eType) {} 76 QString name; 77 LONG port; 78 LONG device; 79 QString id; 80 VBoxDefs::MediumType type; 81 }; 82 Q_DECLARE_METATYPE(MountTarget); 83 84 class UINetworkAdaptersDialog : public QIWithRetranslateUI<QDialog> 85 { 86 Q_OBJECT; 87 97 88 public: 98 enum { Type = QEvent::User + 10 }; 99 StatusTipEvent (const QString &aTip) 100 : QEvent ((QEvent::Type) Type), mTip (aTip) {} 101 102 QString mTip; 89 90 UINetworkAdaptersDialog(QWidget *pParent, CSession &session) 91 : QIWithRetranslateUI<QDialog>(pParent) 92 , m_pSettings(0) 93 , m_session(session) 94 { 95 /* Setup Dialog's options */ 96 setModal(true); 97 setWindowIcon(QIcon(":/nw_16px.png")); 98 setSizeGripEnabled(true); 99 100 /* Setup main dialog's layout */ 101 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 102 VBoxGlobal::setLayoutMargin(pMainLayout, 10); 103 pMainLayout->setSpacing(10); 104 105 /* Setup settings layout */ 106 m_pSettings = new VBoxVMSettingsNetworkPage(true); 107 m_pSettings->setOrderAfter(this); 108 VBoxGlobal::setLayoutMargin(m_pSettings->layout(), 0); 109 m_pSettings->getFrom(m_session.GetMachine()); 110 pMainLayout->addWidget(m_pSettings); 111 112 /* Setup button's layout */ 113 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 114 115 connect(pButtonBox, SIGNAL(helpRequested()), &vboxProblem(), SLOT(showHelpHelpDialog())); 116 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 117 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); 118 pMainLayout->addWidget(pButtonBox); 119 120 retranslateUi(); 121 } 122 123 protected: 124 125 void retranslateUi() 126 { 127 setWindowTitle(tr("Network Adapters")); 128 } 129 130 protected slots: 131 132 virtual void accept() 133 { 134 m_pSettings->putBackTo(); 135 CMachine machine = m_session.GetMachine(); 136 machine.SaveSettings(); 137 if (!machine.isOk()) 138 vboxProblem().cannotSaveMachineSettings(machine); 139 QDialog::accept(); 140 } 141 142 protected: 143 144 void showEvent(QShowEvent *pEvent) 145 { 146 resize(450, 300); 147 VBoxGlobal::centerWidget(this, parentWidget()); 148 setMinimumWidth(400); 149 QDialog::showEvent(pEvent); 150 } 151 152 private: 153 154 VBoxSettingsPage *m_pSettings; 155 CSession &m_session; 103 156 }; 104 157 105 class VBoxAdditionsDownloader : public VBoxDownloaderWgt158 class UISharedFoldersDialog : public QIWithRetranslateUI<QDialog> 106 159 { 107 160 Q_OBJECT; … … 109 162 public: 110 163 111 VBoxAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 164 UISharedFoldersDialog(QWidget *pParent, CSession &session) 165 : QIWithRetranslateUI<QDialog>(pParent) 166 , m_pSettings(0) 167 , m_session(session) 168 { 169 /* Setup Dialog's options */ 170 setModal(true); 171 setWindowIcon(QIcon(":/select_file_16px.png")); 172 setSizeGripEnabled(true); 173 174 /* Setup main dialog's layout */ 175 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 176 VBoxGlobal::setLayoutMargin(pMainLayout, 10); 177 pMainLayout->setSpacing(10); 178 179 /* Setup settings layout */ 180 m_pSettings = new VBoxVMSettingsSF(MachineType | ConsoleType, this); 181 VBoxGlobal::setLayoutMargin(m_pSettings->layout(), 0); 182 m_pSettings->getFromConsole(m_session.GetConsole()); 183 m_pSettings->getFromMachine(m_session.GetMachine()); 184 pMainLayout->addWidget(m_pSettings); 185 186 /* Setup button's layout */ 187 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 188 189 connect(pButtonBox, SIGNAL(helpRequested()), &vboxProblem(), SLOT(showHelpHelpDialog())); 190 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 191 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); 192 pMainLayout->addWidget(pButtonBox); 193 194 retranslateUi(); 195 } 196 197 protected: 198 199 void retranslateUi() 200 { 201 setWindowTitle(tr("Shared Folders")); 202 } 203 204 protected slots: 205 206 virtual void accept() 207 { 208 m_pSettings->putBackToConsole(); 209 m_pSettings->putBackToMachine(); 210 CMachine machine = m_session.GetMachine(); 211 machine.SaveSettings(); 212 if (!machine.isOk()) 213 vboxProblem().cannotSaveMachineSettings(machine); 214 QDialog::accept(); 215 } 216 217 protected: 218 219 void showEvent (QShowEvent *aEvent) 220 { 221 resize(450, 300); 222 VBoxGlobal::centerWidget(this, parentWidget()); 223 setMinimumWidth(400); 224 QDialog::showEvent(aEvent); 225 } 226 227 private: 228 229 VBoxVMSettingsSF *m_pSettings; 230 CSession &m_session; 231 }; 232 233 #if 0 234 class UIAdditionsDownloader : public VBoxDownloaderWgt 235 { 236 Q_OBJECT; 237 238 public: 239 240 UIAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 112 241 : VBoxDownloaderWgt (aSource, aTarget) 113 242 , mAction (aAction) … … 151 280 file.write (receivedData); 152 281 file.close(); 153 if (vboxProblem().confirmMountAdditions (mSource.toString(), 154 QDir::toNativeSeparators (mTarget))) 155 vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 282 //if (vboxProblem().confirmMountAdditions (mSource.toString(),QDir::toNativeSeparators (mTarget))) 283 // vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 156 284 QTimer::singleShot (0, this, SLOT (suicide())); 157 285 break; … … 200 328 QAction *mAction; 201 329 }; 202 203 struct MountTarget 204 { 205 MountTarget() : name (QString ("")), port (0), device (0), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 206 MountTarget (const QString &aName, LONG aPort, LONG aDevice) 207 : name (aName), port (aPort), device (aDevice), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 208 MountTarget (const QString &aName, LONG aPort, LONG aDevice, const QString &aId) 209 : name (aName), port (aPort), device (aDevice), id (aId), type (VBoxDefs::MediumType_Invalid) {} 210 MountTarget (const QString &aName, LONG aPort, LONG aDevice, VBoxDefs::MediumType aType) 211 : name (aName), port (aPort), device (aDevice), id (QString()), type (aType) {} 212 QString name; 213 LONG port; 214 LONG device; 215 QString id; 216 VBoxDefs::MediumType type; 217 }; 218 Q_DECLARE_METATYPE (MountTarget); 219 220 int searchMaxSnapshotIndex (const CMachine &aMachine, const CSnapshot &aSnapshot, const QString &aNameTemplate) 221 { 222 int maxIndex = 0; 223 QRegExp regExp (QString ("^") + aNameTemplate.arg ("([0-9]+)") + QString ("$")); 224 if (!aSnapshot.isNull()) 225 { 226 /* Check the current snapshot name */ 227 QString name = aSnapshot.GetName(); 228 int pos = regExp.indexIn (name); 229 if (pos != -1) 230 maxIndex = regExp.cap (1).toInt() > maxIndex ? regExp.cap (1).toInt() : maxIndex; 231 /* Traversing all the snapshot children */ 232 foreach (const CSnapshot &child, aSnapshot.GetChildren()) 233 { 234 int maxIndexOfChildren = searchMaxSnapshotIndex (aMachine, child, aNameTemplate); 235 maxIndex = maxIndexOfChildren > maxIndex ? maxIndexOfChildren : maxIndex; 236 } 237 } 238 return maxIndex; 239 } 240 241 /** \class VBoxConsoleWnd 242 * 243 * The VBoxConsoleWnd class is a VM console window, one of two main VBox 244 * GUI windows. 245 * 246 * This window appears when the user starts the virtual machine. It 247 * contains the VBoxConsoleView widget that acts as a console of the 248 * running virtual machine. 249 */ 250 251 /** 252 * Constructs the VM console window. 253 * 254 * @param aSelf pointer to a variable where to store |this| right after 255 * this object's constructor is called (necessary to avoid 256 * recursion in VBoxGlobal::consoleWnd()) 257 */ 258 VBoxConsoleWnd::VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent, Qt::WindowFlags aFlags /* = Qt::Window */) 259 : QIWithRetranslateUI2 <QMainWindow> (aParent, aFlags) 260 /* Machine State */ 261 , mMachineState (KMachineState_Null) 262 /* Window Variables */ 263 , mConsoleStyle (0) 264 /* Menu Items */ 265 , mMainMenu (0) 266 , mVMMenu (0) 267 , mVMMenuMini (0) 268 , mDevicesMenu (0) 269 , mDevicesCDMenu (0) 270 , mDevicesFDMenu (0) 271 , mDevicesNetworkMenu (0) 272 , mDevicesSFMenu (0) 273 , mDevicesUSBMenu (0) 274 , mVmDisMouseIntegrMenu (0) 275 #if 0 /* TODO: Allow to setup status-bar! */ 276 , mDevicesVRDPMenu (0) 277 , mVmAutoresizeMenu (0) 278 #endif 330 #endif 331 332 UIMachineLogic* UIMachineLogic::create(QObject *pParent, 333 const CSession &session, 334 UIActionsPool *pActionsPool, 335 UIVisualStateType visualStateType) 336 { 337 UIMachineLogic *logic = 0; 338 switch (visualStateType) 339 { 340 case UIVisualStateType_Normal: 341 logic = new UIMachineLogicNormal(pParent, session, pActionsPool); 342 break; 343 case UIVisualStateType_Fullscreen: 344 // logic = new UIMachineLogicFullscreen(pParent, session, pActionsPool); 345 logic = new UIMachineLogicNormal(pParent, session, pActionsPool); 346 break; 347 case UIVisualStateType_Seamless: 348 // logic = new UIMachineLogicSeamless(pParent, session, pActionsPool); 349 logic = new UIMachineLogicNormal(pParent, session, pActionsPool); 350 break; 351 } 352 return logic; 353 } 354 355 UIMachineLogic::UIMachineLogic(QObject *pParent, 356 const CSession &session, 357 UIActionsPool *pActionsPool, 358 UIVisualStateType visualStateType) 359 : QObject(pParent) 360 , m_pMachineWindowContainer(0) 361 , m_session(session) 362 , m_pActionsPool(pActionsPool) 363 , m_machineState(KMachineState_Null) 364 , m_visualStateType(visualStateType) 365 , m_pRunningActions(0) 366 , m_pRunningOrPausedActions(0) 367 , m_bIsFirstTimeStarted(false) 368 , m_bIsOpenViewFinished(false) 369 , m_bIsGraphicsSupported(false) 370 , m_bIsSeamlessSupported(false) 371 , m_bIsAutoSaveMedia(true) 372 , m_bIsPreventAutoClose(false) 373 { 374 /* Prepare action groups: */ 375 prepareActionGroups(); 376 377 /* Prepare action connections: */ 378 prepareActionConnections(); 379 380 /* Check the status of required features: */ 381 prepareRequiredFeatures(); 382 383 /* Load common logic settings: */ 384 loadLogicSettings(); 385 } 386 387 UIMachineLogic::~UIMachineLogic() 388 { 389 /* Save common logic settings: */ 390 saveLogicSettings(); 391 279 392 #ifdef VBOX_WITH_DEBUGGER_GUI 280 , mDbgMenu (0) 281 #endif 282 , mHelpMenu (0) 283 /* Action Groups */ 284 , mRunningActions (0) 285 , mRunningOrPausedActions (0) 286 /* Machine Menu Actions */ 287 , mVmFullscreenAction (0) 288 , mVmSeamlessAction (0) 289 , mVmAutoresizeGuestAction (0) 290 , mVmAdjustWindowAction (0) 291 , mVmDisableMouseIntegrAction (0) 292 , mVmTypeCADAction (0) 393 /* Close debugger: */ 394 // TODO: Check that logic! 395 //dbgDestroy(); 396 #endif 397 } 398 399 void UIMachineLogic::updateAppearanceOf(int iElement) 400 { 401 CMachine machine = session().GetMachine(); 402 403 bool isRunningOrPaused = machineState() == KMachineState_Running || 404 machineState() == KMachineState_Paused || 405 machineState() == KMachineState_Teleporting || 406 machineState() == KMachineState_LiveSnapshotting; 407 408 if (iElement & UIVisualElement_PauseStuff) 409 { 410 actionsPool()->action(UIActionIndex_Toggle_Pause)->setEnabled(isRunningOrPaused); 411 } 412 } 413 414 void UIMachineLogic::sltAdjustWindow() 415 { 416 if (!machineWindowWrapper()) 417 return; 418 419 if (machineWindowWrapper()->machineWindow()->isMaximized()) 420 machineWindowWrapper()->machineWindow()->showNormal(); 421 422 machineWindowWrapper()->machineView()->normalizeGeometry(true); 423 } 424 425 void UIMachineLogic::sltToggleMouseIntegration(bool aOff) 426 { 427 if (!machineWindowWrapper()) 428 return; 429 430 machineWindowWrapper()->machineView()->setMouseIntegrationEnabled(!aOff); 431 432 updateAppearanceOf(UIVisualElement_MouseIntegrationStuff); 433 } 434 435 void UIMachineLogic::sltTypeCAD() 436 { 437 CKeyboard keyboard = session().GetConsole().GetKeyboard(); 438 Assert(!keyboard.isNull()); 439 keyboard.PutCAD(); 440 AssertWrapperOk(keyboard); 441 } 442 293 443 #ifdef Q_WS_X11 294 , mVmTypeCABSAction (0) 295 #endif 296 , mVmTakeSnapshotAction (0) 297 , mVmShowInformationDlgAction (0) 298 , mVmResetAction (0) 299 , mVmPauseAction (0) 300 , mVmACPIShutdownAction (0) 301 , mVmCloseAction (0) 302 /* Device Menu Actions */ 303 , mDevicesNetworkDialogAction (0) 304 , mDevicesSFDialogAction (0) 305 , mDevicesSwitchVrdpSeparator (0) 306 , mDevicesSwitchVrdpAction (0) 307 , mDevicesInstallGuestToolsAction (0) 308 #ifdef VBOX_WITH_DEBUGGER_GUI 309 /* Debug Menu Actions */ 310 , mDbgStatisticsAction (0) 311 , mDbgCommandLineAction (0) 312 , mDbgLoggingAction (0) 313 #endif 314 /* Widgets */ 315 , mConsole (0) 316 , mMiniToolBar (0) 317 #ifdef VBOX_WITH_DEBUGGER_GUI 318 , mDbgGui (0) 319 , mDbgGuiVT (0) 320 #endif 321 /* LED Update Timer */ 322 , mIdleTimer (new QTimer (this)) 323 /* LEDs */ 324 , mHDLed (0) 325 , mCDLed (0) 326 #if 0 /* TODO: Allow to setup status-bar! */ 327 , mFDLed (0) 328 #endif 329 , mNetLed (0) 330 , mUSBLed (0) 331 , mSFLed (0) 332 , mVirtLed (0) 333 , mMouseLed (0) 334 , mHostkeyLed (0) 335 , mHostkeyLedContainer (0) 336 , mHostkeyName (0) 337 #if 0 /* TODO: Allow to setup status-bar! */ 338 , mVrdpLed (0) 339 , mAutoresizeLed (0) 340 #endif 341 , mIsOpenViewFinished (false) 342 , mIsFirstTimeStarted (false) 343 , mIsAutoSaveMedia (true) 344 , mNoAutoClose (false) 345 , mIsFullscreen (false) 346 , mIsSeamless (false) 347 , mIsSeamlessSupported (false) 348 , mIsGraphicsSupported (false) 349 , mIsWaitingModeResize (false) 350 , mWasMax (false) 351 { 352 if (aSelf) 353 *aSelf = this; 354 355 /* Cache IMedium data! */ 356 vboxGlobal().startEnumeratingMedia(); 357 358 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 359 /* The default application icon (will change to the VM-specific icon in 360 * openView()). On Win32, it's built-in to the executable. On Mac OS X the 361 * icon referenced in info.plist is used. */ 362 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 363 #endif 364 365 /* Ensure status bar is created */ 366 setStatusBar (new QIStatusBar (this)); 367 368 /* A group for all actions that are enabled only when the VM is running. 369 * Note that only actions whose enabled state depends exclusively on the 370 * execution state of the VM are added to this group. */ 371 mRunningActions = new QActionGroup (this); 372 mRunningActions->setExclusive (false); 373 374 /* A group for all actions that are enabled when the VM is running or 375 * paused. Note that only actions whose enabled state depends exclusively 376 * on the execution state of the VM are added to this group. */ 377 mRunningOrPausedActions = new QActionGroup (this); 378 mRunningOrPausedActions->setExclusive (false); 379 380 /* VM menu actions */ 381 mVmFullscreenAction = new QAction (this); 382 mVmFullscreenAction->setIcon (VBoxGlobal::iconSetOnOff ( 383 ":/fullscreen_on_16px.png", ":/fullscreen_16px.png", 384 ":/fullscreen_on_disabled_16px.png", ":/fullscreen_disabled_16px.png")); 385 mVmFullscreenAction->setCheckable (true); 386 387 mVmSeamlessAction = new QAction (this); 388 mVmSeamlessAction->setIcon (VBoxGlobal::iconSetOnOff ( 389 ":/seamless_on_16px.png", ":/seamless_16px.png", 390 ":/seamless_on_disabled_16px.png", ":/seamless_disabled_16px.png")); 391 mVmSeamlessAction->setCheckable (true); 392 393 mVmAutoresizeGuestAction = new QAction (mRunningActions); 394 mVmAutoresizeGuestAction->setIcon (VBoxGlobal::iconSetOnOff ( 395 ":/auto_resize_on_on_16px.png", ":/auto_resize_on_16px.png", 396 ":/auto_resize_on_on_disabled_16px.png", ":/auto_resize_on_disabled_16px.png")); 397 mVmAutoresizeGuestAction->setCheckable (true); 398 mVmAutoresizeGuestAction->setEnabled (false); 399 400 mVmAdjustWindowAction = new QAction (this); 401 mVmAdjustWindowAction->setIcon (VBoxGlobal::iconSet ( 402 ":/adjust_win_size_16px.png", ":/adjust_win_size_disabled_16px.png")); 403 404 mVmDisableMouseIntegrAction = new QAction (this); 405 mVmDisableMouseIntegrAction->setIcon (VBoxGlobal::iconSetOnOff ( 406 ":/mouse_can_seamless_on_16px.png", ":/mouse_can_seamless_16px.png", 407 ":/mouse_can_seamless_on_disabled_16px.png", ":/mouse_can_seamless_disabled_16px.png")); 408 mVmDisableMouseIntegrAction->setCheckable (true); 409 410 mVmTypeCADAction = new QAction (mRunningActions); 411 mVmTypeCADAction->setIcon (VBoxGlobal::iconSet ( 412 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 413 414 #if defined(Q_WS_X11) 415 mVmTypeCABSAction = new QAction (mRunningActions); 416 mVmTypeCABSAction->setIcon (VBoxGlobal::iconSet ( 417 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 418 #endif 419 420 mVmTakeSnapshotAction = new QAction (mRunningOrPausedActions); 421 mVmTakeSnapshotAction->setIcon (VBoxGlobal::iconSet ( 422 ":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png")); 423 424 mVmShowInformationDlgAction = new QAction (this); 425 mVmShowInformationDlgAction->setIcon (VBoxGlobal::iconSet ( 426 ":/session_info_16px.png", ":/session_info_disabled_16px.png")); 427 428 mVmResetAction = new QAction (mRunningActions); 429 mVmResetAction->setIcon (VBoxGlobal::iconSet ( 430 ":/reset_16px.png", ":/reset_disabled_16px.png")); 431 432 mVmPauseAction = new QAction (this); 433 mVmPauseAction->setIcon (VBoxGlobal::iconSet ( 434 ":/pause_16px.png", ":/pause_disabled_16px.png")); 435 mVmPauseAction->setCheckable (true); 436 437 mVmACPIShutdownAction = new QAction (mRunningActions); 438 mVmACPIShutdownAction->setIcon (VBoxGlobal::iconSet ( 439 ":/acpi_16px.png", ":/acpi_disabled_16px.png")); 440 441 mVmCloseAction = new QAction (this); 442 mVmCloseAction->setMenuRole (QAction::QuitRole); 443 mVmCloseAction->setIcon (VBoxGlobal::iconSet (":/exit_16px.png")); 444 445 /* Devices menu actions */ 446 mDevicesNetworkDialogAction = new QAction (mRunningOrPausedActions); 447 mDevicesNetworkDialogAction->setIcon (VBoxGlobal::iconSet ( 448 ":/nw_16px.png", ":/nw_disabled_16px.png")); 449 450 mDevicesSFDialogAction = new QAction (mRunningOrPausedActions); 451 mDevicesSFDialogAction->setIcon (VBoxGlobal::iconSet ( 452 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")); 453 454 mDevicesSwitchVrdpAction = new QAction (mRunningOrPausedActions); 455 mDevicesSwitchVrdpAction->setIcon (VBoxGlobal::iconSetOnOff ( 456 ":/vrdp_on_16px.png", ":/vrdp_16px.png", 457 ":/vrdp_on_disabled_16px.png", ":/vrdp_disabled_16px.png")); 458 mDevicesSwitchVrdpAction->setCheckable (true); 459 460 mDevicesInstallGuestToolsAction = new QAction (mRunningActions); 461 mDevicesInstallGuestToolsAction->setIcon (VBoxGlobal::iconSet ( 462 ":/guesttools_16px.png", ":/guesttools_disabled_16px.png")); 463 464 #ifdef VBOX_WITH_DEBUGGER_GUI 465 /* Debug menu actions */ 466 if (vboxGlobal().isDebuggerEnabled()) 467 { 468 mDbgStatisticsAction = new QAction (this); 469 mDbgCommandLineAction = new QAction (this); 470 if (vboxGlobal().getDebuggerModule()== NIL_RTLDRMOD) 471 { 472 mDbgStatisticsAction->setEnabled (false); 473 mDbgCommandLineAction->setEnabled (false); 474 } 475 mDbgLoggingAction = new QAction (this); 476 mDbgLoggingAction->setCheckable (true); 477 } 478 else 479 { 480 mDbgStatisticsAction = 0; 481 mDbgCommandLineAction = 0; 482 mDbgLoggingAction = 0; 483 } 484 #endif 485 486 /* Help menu actions */ 487 mHelpActions.setup (this); 488 489 /* Menu Items */ 490 mMainMenu = new QIMenu (this); 491 mDevicesCDMenu = new QMenu (this); 492 mDevicesFDMenu = new QMenu (this); 493 mDevicesNetworkMenu = new QMenu (this); 494 mDevicesSFMenu = new QMenu (this); 495 mDevicesUSBMenu = new VBoxUSBMenu (this); 496 497 /* Machine submenu */ 498 mVMMenu = menuBar()->addMenu (QString::null); 499 mMainMenu->addMenu (mVMMenu); 500 mVmDisMouseIntegrMenu = new VBoxSwitchMenu (mVMMenu, mVmDisableMouseIntegrAction, true); 501 #if 0 /* TODO: Allow to setup status-bar! */ 502 mVmAutoresizeMenu = new VBoxSwitchMenu (mVMMenu, mVmAutoresizeGuestAction); 503 #endif 504 505 mVMMenu->addAction (mVmFullscreenAction); 506 mVMMenu->addAction (mVmSeamlessAction); 507 mVMMenu->addAction (mVmAutoresizeGuestAction); 508 mVMMenu->addAction (mVmAdjustWindowAction); 509 mVMMenu->addSeparator(); 510 mVMMenu->addAction (mVmDisableMouseIntegrAction); 511 mVMMenu->addSeparator(); 512 mVMMenu->addAction (mVmTypeCADAction); 513 #ifdef Q_WS_X11 514 mVMMenu->addAction (mVmTypeCABSAction); 515 #endif 516 mVMMenu->addSeparator(); 517 mVMMenu->addAction (mVmTakeSnapshotAction); 518 mVMMenu->addSeparator(); 519 mVMMenu->addAction (mVmShowInformationDlgAction); 520 mVMMenu->addSeparator(); 521 mVMMenu->addAction (mVmResetAction); 522 mVMMenu->addAction (mVmPauseAction); 523 mVMMenu->addAction (mVmACPIShutdownAction); 524 #ifndef Q_WS_MAC 525 mVMMenu->addSeparator(); 526 #endif /* Q_WS_MAC */ 527 mVMMenu->addAction (mVmCloseAction); 528 529 /* Devices submenu */ 530 mDevicesMenu = menuBar()->addMenu (QString::null); 531 mMainMenu->addMenu (mDevicesMenu); 532 533 mDevicesCDMenu->setIcon (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png")); 534 mDevicesFDMenu->setIcon (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png")); 535 mDevicesUSBMenu->setIcon (VBoxGlobal::iconSet (":/usb_16px.png", ":/usb_disabled_16px.png")); 536 537 mDevicesMenu->addMenu (mDevicesCDMenu); 538 mDevicesMenu->addMenu (mDevicesFDMenu); 539 mDevicesMenu->addAction (mDevicesNetworkDialogAction); 540 mDevicesMenu->addAction (mDevicesSFDialogAction); 541 mDevicesMenu->addMenu (mDevicesUSBMenu); 542 543 #if 0 /* TODO: Allow to setup status-bar! */ 544 mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, mDevicesSwitchVrdpAction); 545 #endif 546 mDevicesSwitchVrdpSeparator = mDevicesMenu->addSeparator(); 547 mDevicesMenu->addAction (mDevicesSwitchVrdpAction); 548 549 mDevicesMenu->addSeparator(); 550 mDevicesMenu->addAction (mDevicesInstallGuestToolsAction); 551 552 #ifdef VBOX_WITH_DEBUGGER_GUI 553 /* Debug submenu */ 554 if (vboxGlobal().isDebuggerEnabled()) 555 { 556 mDbgMenu = menuBar()->addMenu (QString::null); 557 mMainMenu->addMenu (mDbgMenu); 558 mDbgMenu->addAction (mDbgStatisticsAction); 559 mDbgMenu->addAction (mDbgCommandLineAction); 560 mDbgMenu->addAction (mDbgLoggingAction); 561 } 562 else 563 mDbgMenu = 0; 564 #endif 565 566 /* Help submenu */ 567 mHelpMenu = menuBar()->addMenu (QString::null); 568 mMainMenu->addMenu (mHelpMenu); 569 mHelpActions.addTo (mHelpMenu); 570 571 /* Machine submenu for mini-toolbar */ 572 mVMMenuMini = new QMenu (this); 573 mVMMenuMini->addAction (mVmTypeCADAction); 574 #ifdef Q_WS_X11 575 mVMMenuMini->addAction (mVmTypeCABSAction); 576 #endif 577 mVMMenuMini->addSeparator(); 578 mVMMenuMini->addAction (mVmTakeSnapshotAction); 579 mVMMenuMini->addSeparator(); 580 mVMMenuMini->addAction (mVmShowInformationDlgAction); 581 mVMMenuMini->addSeparator(); 582 mVMMenuMini->addAction (mVmResetAction); 583 mVMMenuMini->addAction (mVmPauseAction); 584 mVMMenuMini->addAction (mVmACPIShutdownAction); 585 586 /* Status bar */ 587 QWidget *indicatorBox = new QWidget; 588 QHBoxLayout *indicatorBoxHLayout = new QHBoxLayout (indicatorBox); 589 VBoxGlobal::setLayoutMargin (indicatorBoxHLayout, 0); 590 indicatorBoxHLayout->setSpacing (5); 591 592 /* i/o devices */ 593 mHDLed = new QIStateIndicator (KDeviceActivity_Idle); 594 mHDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/hd_16px.png")); 595 mHDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/hd_read_16px.png")); 596 mHDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/hd_write_16px.png")); 597 mHDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/hd_disabled_16px.png")); 598 indicatorBoxHLayout->addWidget (mHDLed); 599 mCDLed = new QIStateIndicator (KDeviceActivity_Idle); 600 mCDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/cd_16px.png")); 601 mCDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/cd_read_16px.png")); 602 mCDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/cd_write_16px.png")); 603 mCDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/cd_disabled_16px.png")); 604 indicatorBoxHLayout->addWidget (mCDLed); 605 #if 0 /* TODO: Allow to setup status-bar! */ 606 mFDLed = new QIStateIndicator (KDeviceActivity_Idle); 607 mFDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/fd_16px.png")); 608 mFDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/fd_read_16px.png")); 609 mFDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/fd_write_16px.png")); 610 mFDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/fd_disabled_16px.png")); 611 indicatorBoxHLayout->addWidget (mFDLed); 612 #endif 613 mNetLed = new QIStateIndicator (KDeviceActivity_Idle); 614 mNetLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/nw_16px.png")); 615 mNetLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/nw_read_16px.png")); 616 mNetLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/nw_write_16px.png")); 617 mNetLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/nw_disabled_16px.png")); 618 indicatorBoxHLayout->addWidget (mNetLed); 619 mUSBLed = new QIStateIndicator (KDeviceActivity_Idle); 620 mUSBLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/usb_16px.png")); 621 mUSBLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/usb_read_16px.png")); 622 mUSBLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/usb_write_16px.png")); 623 mUSBLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/usb_disabled_16px.png")); 624 indicatorBoxHLayout->addWidget (mUSBLed); 625 mSFLed = new QIStateIndicator (KDeviceActivity_Idle); 626 mSFLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/shared_folder_16px.png")); 627 mSFLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/shared_folder_read_16px.png")); 628 mSFLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/shared_folder_write_16px.png")); 629 mSFLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/shared_folder_disabled_16px.png")); 630 indicatorBoxHLayout->addWidget (mSFLed); 631 632 /* virtualization */ 633 mVirtLed = new QIStateIndicator (0); 634 mVirtLed->setStateIcon (0, QPixmap (":/vtx_amdv_disabled_16px.png")); 635 mVirtLed->setStateIcon (1, QPixmap (":/vtx_amdv_16px.png")); 636 indicatorBoxHLayout->addWidget (mVirtLed); 637 638 QFrame *separator = new QFrame(); 639 separator->setFrameStyle (QFrame::VLine | QFrame::Sunken); 640 indicatorBoxHLayout->addWidget (separator); 641 642 /* mouse */ 643 mMouseLed = new QIStateIndicator (0); 644 mMouseLed->setStateIcon (0, QPixmap (":/mouse_disabled_16px.png")); 645 mMouseLed->setStateIcon (1, QPixmap (":/mouse_16px.png")); 646 mMouseLed->setStateIcon (2, QPixmap (":/mouse_seamless_16px.png")); 647 mMouseLed->setStateIcon (3, QPixmap (":/mouse_can_seamless_16px.png")); 648 mMouseLed->setStateIcon (4, QPixmap (":/mouse_can_seamless_uncaptured_16px.png")); 649 indicatorBoxHLayout->addWidget (mMouseLed); 650 651 /* host key */ 652 mHostkeyLedContainer = new QWidget; 653 QHBoxLayout *hostkeyLEDContainerLayout = new QHBoxLayout (mHostkeyLedContainer); 654 VBoxGlobal::setLayoutMargin (hostkeyLEDContainerLayout, 0); 655 hostkeyLEDContainerLayout->setSpacing (3); 656 indicatorBoxHLayout->addWidget (mHostkeyLedContainer); 657 658 mHostkeyLed = new QIStateIndicator (0); 659 mHostkeyLed->setStateIcon (0, QPixmap (":/hostkey_16px.png")); 660 mHostkeyLed->setStateIcon (1, QPixmap (":/hostkey_captured_16px.png")); 661 mHostkeyLed->setStateIcon (2, QPixmap (":/hostkey_pressed_16px.png")); 662 mHostkeyLed->setStateIcon (3, QPixmap (":/hostkey_captured_pressed_16px.png")); 663 hostkeyLEDContainerLayout->addWidget (mHostkeyLed); 664 mHostkeyName = new QLabel (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 665 hostkeyLEDContainerLayout->addWidget (mHostkeyName); 666 667 #if 0 /* TODO: Allow to setup status-bar! */ 668 /* VRDP Led */ 669 mVrdpLed = new QIStateIndicator (0, indicatorBox, "mVrdpLed", Qt::WNoAutoErase); 670 mVrdpLed->setStateIcon (0, QPixmap (":/vrdp_disabled_16px.png")); 671 mVrdpLed->setStateIcon (1, QPixmap (":/vrdp_16px.png")); 672 /* Auto-Resize LED */ 673 mAutoresizeLed = new QIStateIndicator (1, indicatorBox, "mAutoresizeLed", Qt::WNoAutoErase); 674 mAutoresizeLed->setStateIcon (0, QPixmap (":/auto_resize_off_disabled_16px.png")); 675 mAutoresizeLed->setStateIcon (1, QPixmap (":/auto_resize_off_16px.png")); 676 mAutoresizeLed->setStateIcon (2, QPixmap (":/auto_resize_on_disabled_16px.png")); 677 mAutoresizeLed->setStateIcon (3, QPixmap (":/auto_resize_on_16px.png")); 678 #endif 679 680 /* add to statusbar */ 681 statusBar()->addPermanentWidget (indicatorBox, 0); 682 683 /* Retranslate UI */ 684 retranslateUi(); 685 686 setWindowTitle (mCaptionPrefix); 687 688 /* Connections */ 689 connect (mVmFullscreenAction, SIGNAL (toggled (bool)), this, SLOT (vmFullscreen (bool))); 690 connect (mVmSeamlessAction, SIGNAL (toggled (bool)), this, SLOT (vmSeamless (bool))); 691 connect (mVmAutoresizeGuestAction, SIGNAL (toggled (bool)), this, SLOT (vmAutoresizeGuest (bool))); 692 connect (mVmAdjustWindowAction, SIGNAL (triggered()), this, SLOT (vmAdjustWindow())); 693 connect (mVmDisableMouseIntegrAction, SIGNAL (toggled (bool)), this, SLOT (vmDisableMouseIntegration (bool))); 694 connect (mVmTypeCADAction, SIGNAL (triggered()), this, SLOT (vmTypeCAD())); 695 #ifdef Q_WS_X11 696 connect (mVmTypeCABSAction, SIGNAL (triggered()), this, SLOT (vmTypeCABS())); 697 #endif 698 connect (mVmTakeSnapshotAction, SIGNAL (triggered()), this, SLOT (vmTakeSnapshot())); 699 connect (mVmShowInformationDlgAction, SIGNAL (triggered()), this, SLOT (vmShowInfoDialog())); 700 connect (mVmResetAction, SIGNAL (triggered()), this, SLOT (vmReset())); 701 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 702 connect (mVmACPIShutdownAction, SIGNAL (triggered()), this, SLOT (vmACPIShutdown())); 703 connect (mVmCloseAction, SIGNAL (triggered()), this, SLOT (vmClose())); 704 705 connect (mDevicesCDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 706 connect (mDevicesFDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 707 connect (mDevicesNetworkMenu, SIGNAL (aboutToShow()), this, SLOT (prepareNetworkMenu())); 708 connect (mDevicesSFMenu, SIGNAL (aboutToShow()), this, SLOT (prepareSFMenu())); 709 connect (mDevicesUSBMenu, SIGNAL(triggered (QAction *)), this, SLOT(switchUSB (QAction *))); 710 711 connect (mDevicesNetworkDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenNetworkDialog())); 712 connect (mDevicesSFDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenSFDialog())); 713 connect (mDevicesSwitchVrdpAction, SIGNAL (toggled (bool)), this, SLOT (devicesSwitchVrdp (bool))); 714 connect (mDevicesInstallGuestToolsAction, SIGNAL (triggered()), this, SLOT (devicesInstallGuestAdditions())); 715 716 connect (mCDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 717 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 718 #if 0 /* TODO: Allow to setup status-bar! */ 719 connect (mFDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 720 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 721 #endif 722 connect (mNetLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 723 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 724 connect (mUSBLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 725 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 726 connect (mSFLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 727 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 728 connect (mMouseLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 729 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 730 #if 0 /* TODO: Allow to setup status-bar! */ 731 connect (mVrdpLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 732 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 733 connect (mAutoresizeLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 734 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 735 #endif 736 737 /* Watch global settings changes */ 738 connect (&vboxGlobal().settings(), SIGNAL (propertyChanged (const char *, const char *)), 739 this, SLOT (processGlobalSettingChange (const char *, const char *))); 740 #ifdef Q_WS_MAC 741 connect (&vboxGlobal(), SIGNAL (dockIconUpdateChanged (const VBoxChangeDockIconUpdateEvent &)), 742 this, SLOT (changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &))); 743 connect (&vboxGlobal(), SIGNAL (presentationModeChanged (const VBoxChangePresentationModeEvent &)), 744 this, SLOT (changePresentationMode (const VBoxChangePresentationModeEvent &))); 745 #endif 746 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 if (mDbgMenu) 749 connect (mDbgMenu, SIGNAL (aboutToShow()), this, SLOT (dbgPrepareDebugMenu())); 750 if (mDbgStatisticsAction) 751 connect (mDbgStatisticsAction, SIGNAL (triggered()), this, SLOT (dbgShowStatistics())); 752 if (mDbgCommandLineAction) 753 connect (mDbgCommandLineAction, SIGNAL (triggered()), this, SLOT (dbgShowCommandLine())); 754 if (mDbgLoggingAction) 755 connect (mDbgLoggingAction, SIGNAL (toggled (bool)), this, SLOT (dbgLoggingToggled (bool))); 756 #endif 757 758 #ifdef Q_WS_MAC 759 /* For the status bar on Cocoa */ 760 setUnifiedTitleAndToolBarOnMac (true); 761 # ifdef VBOX_WITH_ICHAT_THEATER 762 // int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 }; 763 // HIWindowChangeAttributes (window, setAttr, 0); 764 initSharedAVManager(); 765 # endif 766 #endif 767 768 mMaskShift.scale (0, 0, Qt::IgnoreAspectRatio); 769 } 770 771 VBoxConsoleWnd::~VBoxConsoleWnd() 772 { 773 closeView(); 774 775 #ifdef VBOX_WITH_DEBUGGER_GUI 776 dbgDestroy(); 777 #endif 778 } 779 780 /** 781 * Opens a new console view to interact with a given VM. 782 * Does nothing if the console view is already opened. 783 * Used by VBoxGlobal::startMachine(), should not be called directly. 784 */ 785 bool VBoxConsoleWnd::openView (const CSession &aSession) 786 { 787 LogFlowFuncEnter(); 788 789 if (mConsole) 790 { 791 LogFlowFunc (("Already opened\n")); 792 LogFlowFuncLeave(); 793 return false; 794 } 795 796 #ifdef Q_WS_MAC 797 /* We have to make sure that we are getting the front most process. This is 798 * necessary for Qt versions > 4.3.3 */ 799 ProcessSerialNumber psn = { 0, kCurrentProcess }; 800 ::SetFrontProcess (&psn); 801 #endif /* Q_WS_MAC */ 802 803 mSession = aSession; 804 805 if (!centralWidget()) 806 { 807 setCentralWidget (new QWidget (this)); 808 QGridLayout *pMainLayout = new QGridLayout (centralWidget()); 809 VBoxGlobal::setLayoutMargin (pMainLayout, 0); 810 pMainLayout->setSpacing (0); 811 812 mShiftingSpacerLeft = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 813 mShiftingSpacerTop = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 814 mShiftingSpacerRight = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 815 mShiftingSpacerBottom = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 816 pMainLayout->addItem (mShiftingSpacerTop, 0, 0, 1, -1); 817 pMainLayout->addItem (mShiftingSpacerLeft, 1, 0); 818 pMainLayout->addItem (mShiftingSpacerRight, 1, 2); 819 pMainLayout->addItem (mShiftingSpacerBottom, 2, 0, 1, -1); 820 } 821 822 mVmPauseAction->setChecked (false); 823 824 CConsole console = mSession.GetConsole(); 825 AssertWrapperOk (mSession); 826 827 CMachine machine = mSession.GetMachine(); 828 829 #ifdef VBOX_WITH_VIDEOHWACCEL 830 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled */ 831 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() 832 && VBoxGlobal::isAcceleration2DVideoAvailable() 833 ; 834 #endif 835 836 mConsole = new VBoxConsoleView (this, console, vboxGlobal().vmRenderMode(), 837 #ifdef VBOX_WITH_VIDEOHWACCEL 838 bAccelerate2DVideo, 839 #endif 840 centralWidget()); 841 qobject_cast <QGridLayout*> (centralWidget()->layout())->addWidget (mConsole, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 842 843 /* Mini toolbar */ 844 bool isActive = !(machine.GetExtraData (VBoxDefs::GUI_ShowMiniToolBar) == "no"); 845 bool isAtTop = (machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAlignment) == "top"); 846 bool isAutoHide = !(machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide) == "off"); 847 QList <QMenu*> menus (QList <QMenu*>() << mVMMenuMini << mDevicesMenu); 848 mMiniToolBar = new VBoxMiniToolBar (centralWidget(), isAtTop ? VBoxMiniToolBar::AlignTop : VBoxMiniToolBar::AlignBottom, 849 isActive, isAutoHide); 850 *mMiniToolBar << menus; 851 connect (mMiniToolBar, SIGNAL (exitAction()), this, SLOT (mtExitMode())); 852 connect (mMiniToolBar, SIGNAL (closeAction()), this, SLOT (mtCloseVM())); 853 connect (mMiniToolBar, SIGNAL (geometryUpdated()), this, SLOT (mtMaskUpdate())); 854 connect (this, SIGNAL (closing()), mMiniToolBar, SLOT (close())); 855 856 activateUICustomizations(); 857 858 /* Set the VM-specific application icon */ 859 /* Not on Mac OS X. The dock icon is handled below. */ 860 #ifndef Q_WS_MAC 861 setWindowIcon (vboxGlobal().vmGuestOSTypeIcon (machine.GetOSTypeId())); 862 #endif 863 864 /* Restore the position of the window and some options */ 865 { 866 QString str = machine.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 867 868 bool ok = false, max = false; 869 int x = 0, y = 0, w = 0, h = 0; 870 x = str.section (',', 0, 0).toInt (&ok); 871 if (ok) 872 y = str.section (',', 1, 1).toInt (&ok); 873 if (ok) 874 w = str.section (',', 2, 2).toInt (&ok); 875 if (ok) 876 h = str.section (',', 3, 3).toInt (&ok); 877 if (ok) 878 max = str.section (',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 879 880 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 881 QApplication::desktop()->availableGeometry (this); 882 883 if (ok /* previous parameters were read correctly */) 884 { 885 mNormalGeo = QRect (x, y, w, h); 886 setGeometry (mNormalGeo); 887 888 /* Normalize to the optimal size */ 889 mConsole->normalizeGeometry (true /* adjustPosition */); 890 891 if (max) 892 { 893 /* Maximize if needed */ 894 setWindowState (windowState() | Qt::WindowMaximized); 895 mWasMax = max; 896 } 444 void UIMachineLogic::sltTypeCABS() 445 { 446 CKeyboard keyboard = session().GetConsole().GetKeyboard(); 447 Assert (!keyboard.isNull()); 448 static QVector<LONG> aSequence(6); 449 aSequence[0] = 0x1d; /* Ctrl down */ 450 aSequence[1] = 0x38; /* Alt down */ 451 aSequence[2] = 0x0E; /* Backspace down */ 452 aSequence[3] = 0x8E; /* Backspace up */ 453 aSequence[4] = 0xb8; /* Alt up */ 454 aSequence[5] = 0x9d; /* Ctrl up */ 455 keyboard.PutScancodes(aSequence); 456 AssertWrapperOk(keyboard); 457 } 458 #endif 459 460 void UIMachineLogic::sltTakeSnapshot() 461 { 462 if (!machineWindowWrapper()) 463 return; 464 465 /* Remember the paused state. */ 466 bool bWasPaused = m_machineState == KMachineState_Paused; 467 if (!bWasPaused) 468 { 469 /* Suspend the VM and ignore the close event if failed to do so. 470 * pause() will show the error message to the user. */ 471 if (!pause(true)) 472 return; 473 } 474 475 CMachine machine = session().GetMachine(); 476 477 VBoxTakeSnapshotDlg dlg(machineWindowWrapper()->machineWindow(), machine); 478 479 QString strTypeId = machine.GetOSTypeId(); 480 dlg.mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(strTypeId)); 481 482 /* Search for the max available filter index. */ 483 QString strNameTemplate = tr("Snapshot %1"); 484 int iMaxSnapshotIndex = searchMaxSnapshotIndex(machine, machine.GetSnapshot(QString()), strNameTemplate); 485 dlg.mLeName->setText(strNameTemplate.arg(++ iMaxSnapshotIndex)); 486 487 if (dlg.exec() == QDialog::Accepted) 488 { 489 CConsole console = session().GetConsole(); 490 491 CProgress progress = console.TakeSnapshot(dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 492 493 if (console.isOk()) 494 { 495 /* Show the "Taking Snapshot" progress dialog */ 496 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineWindow(), 0); 497 498 if (progress.GetResultCode() != 0) 499 vboxProblem().cannotTakeSnapshot(progress); 897 500 } 898 501 else 899 { 900 /* Normalize to the optimal size */ 901 mConsole->normalizeGeometry (true /* adjustPosition */); 902 903 /* Move newly created window to the screen center. */ 904 mNormalGeo = geometry(); 905 mNormalGeo.moveCenter (ar.center()); 906 setGeometry (mNormalGeo); 907 } 908 909 show(); 910 911 /* Process show & possible maximize events */ 912 qApp->processEvents(); 913 914 mVmSeamlessAction->setEnabled (false); 915 str = machine.GetExtraData (VBoxDefs::GUI_Seamless); 916 if (str == "on") 917 mVmSeamlessAction->setChecked (true); 918 919 str = machine.GetExtraData (VBoxDefs::GUI_AutoresizeGuest); 920 if (str != "off") 921 mVmAutoresizeGuestAction->setChecked (true); 922 923 str = machine.GetExtraData (VBoxDefs::GUI_FirstRun); 924 if (str == "yes") 925 mIsFirstTimeStarted = true; 926 else if (!str.isEmpty()) 927 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 928 929 str = machine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime); 930 if (str == "no") 931 mIsAutoSaveMedia = false; 932 933 /* Check if one of extended modes to be activated on loading */ 934 QString fsMode = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 935 QString slMode = machine.GetExtraData (VBoxDefs::GUI_Seamless); 936 bool extendedMode = fsMode == "on" || slMode == "on"; 937 938 /* If one of extended modes to be loaded we have to ignore default 939 * console resize event which will come from VGA Device on loading. */ 940 if (extendedMode) 941 mConsole->requestToResize (QSize (w, h - menuBar()->height() - statusBar()->height())); 942 } 943 944 /* initialize storage stuff */ 945 int cdDevicesCount = 0; 946 int fdDevicesCount = 0; 502 vboxProblem().cannotTakeSnapshot(console); 503 } 504 505 /* Restore the running state if needed. */ 506 if (!bWasPaused) 507 pause(false); 508 } 509 510 void UIMachineLogic::sltShowInformationDialog() 511 { 512 // TODO: Call for singleton information dialog for this machine! 513 //VBoxVMInformationDlg::createInformationDlg(session(), machineWindowWrapper()->machineWindow()); 514 } 515 516 void UIMachineLogic::sltReset() 517 { 518 if (!machineWindowWrapper()) 519 return; 520 521 if (vboxProblem().confirmVMReset(machineWindowWrapper()->machineWindow())) 522 session().GetConsole().Reset(); 523 } 524 525 void UIMachineLogic::sltPause(bool aOn) 526 { 527 if (!machineWindowWrapper()) 528 return; 529 530 pause(aOn); 531 532 updateAppearanceOf(UIVisualElement_PauseStuff); 533 } 534 535 void UIMachineLogic::sltACPIShutdown() 536 { 537 if (!machineWindowWrapper()) 538 return; 539 540 CConsole console = session().GetConsole(); 541 542 if (!console.GetGuestEnteredACPIMode()) 543 return vboxProblem().cannotSendACPIToMachine(); 544 545 console.PowerButton(); 546 if (!console.isOk()) 547 vboxProblem().cannotACPIShutdownMachine(console); 548 } 549 550 void UIMachineLogic::sltClose() 551 { 552 if (!machineWindowWrapper()) 553 return; 554 555 machineWindowWrapper()->machineWindow()->close(); 556 } 557 558 void UIMachineLogic::sltPrepareStorageMenu() 559 { 560 QMenu *pMenu = qobject_cast<QMenu*>(sender()); 561 AssertMsg(pMenu, ("This slot should only be called on hovering storage menu!\n")); 562 pMenu->clear(); 563 564 QMenu *pOpticalDevicesMenu = actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu(); 565 QMenu *pFloppyDevicesMenu = actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu(); 566 567 KDeviceType deviceType = pMenu == pOpticalDevicesMenu ? KDeviceType_DVD : 568 pMenu == pFloppyDevicesMenu ? KDeviceType_Floppy : 569 KDeviceType_Null; 570 AssertMsg(deviceType != KDeviceType_Null, ("Incorrect storage device type!\n")); 571 572 VBoxDefs::MediumType mediumType = pMenu == pOpticalDevicesMenu ? VBoxDefs::MediumType_DVD : 573 pMenu == pFloppyDevicesMenu ? VBoxDefs::MediumType_Floppy : 574 VBoxDefs::MediumType_Invalid; 575 AssertMsg(mediumType != VBoxDefs::MediumType_Invalid, ("Incorrect storage medium type!\n")); 576 577 CMachine machine = session().GetMachine(); 947 578 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 948 579 foreach (const CMediumAttachment &attachment, attachments) 949 580 { 950 if (attachment.GetType() == KDeviceType_DVD) 951 ++ cdDevicesCount; 952 if (attachment.GetType() == KDeviceType_Floppy) 953 ++ fdDevicesCount; 954 } 955 mDevicesCDMenu->menuAction()->setData (cdDevicesCount); 956 mDevicesFDMenu->menuAction()->setData (fdDevicesCount); 957 mDevicesCDMenu->menuAction()->setVisible (cdDevicesCount); 958 mDevicesFDMenu->menuAction()->setVisible (fdDevicesCount); 959 960 /* initialize usb stuff */ 961 CUSBController usbctl = machine.GetUSBController(); 962 if (usbctl.isNull()) 963 { 964 /* hide usb_menu & usb_separator & usb_status_led */ 965 mDevicesUSBMenu->setVisible (false); 966 mUSBLed->setHidden (true); 967 } 968 else 969 { 970 bool isUSBEnabled = usbctl.GetEnabled(); 971 mDevicesUSBMenu->setEnabled (isUSBEnabled); 972 mDevicesUSBMenu->setConsole (console); 973 mUSBLed->setState (isUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null); 974 } 975 976 /* initialize vrdp stuff */ 977 CVRDPServer vrdpsrv = machine.GetVRDPServer(); 978 if (vrdpsrv.isNull()) 979 { 980 /* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */ 981 mDevicesSwitchVrdpAction->setVisible (false); 982 mDevicesSwitchVrdpSeparator->setVisible (false); 983 #if 0 /* TODO: Allow to setup status-bar! */ 984 mVrdpLed->setHidden (true); 985 #endif 986 } 987 988 /* start an idle timer that will update device lighths */ 989 connect (mIdleTimer, SIGNAL (timeout()), SLOT (updateDeviceLights())); 990 mIdleTimer->start (50); 991 992 connect (mConsole, SIGNAL (mouseStateChanged (int)), this, SLOT (updateMouseState (int))); 993 connect (mConsole, SIGNAL (keyboardStateChanged (int)), mHostkeyLed, SLOT (setState (int))); 994 connect (mConsole, SIGNAL (machineStateChanged (KMachineState)), this, SLOT (updateMachineState (KMachineState))); 995 connect (mConsole, SIGNAL (additionsStateChanged (const QString&, bool, bool, bool)), 996 this, SLOT (updateAdditionsState (const QString &, bool, bool, bool))); 997 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), 998 this, SLOT (updateMediaDriveState (VBoxDefs::MediumType))); 999 connect (mConsole, SIGNAL (usbStateChange()), this, SLOT (updateUsbState())); 1000 connect (mConsole, SIGNAL (networkStateChange()), this, SLOT (updateNetworkAdaptersState())); 1001 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateSharedFoldersState())); 1002 1003 #ifdef Q_WS_MAC 1004 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 1005 /* Default to true if it is an empty value */ 1006 bool f = (testStr.isEmpty() || testStr == "true"); 1007 mConsole->setDockIconEnabled (f); 1008 mConsole->updateDockOverlay(); 1009 #endif 1010 1011 /* set the correct initial mMachineState value */ 1012 mMachineState = console.GetState(); 1013 1014 mConsole->normalizeGeometry (false /* adjustPosition */); 1015 1016 updateAppearanceOf (AllStuff); 1017 1018 if (vboxGlobal().settings().autoCapture()) 1019 vboxProblem().remindAboutAutoCapture(); 1020 1021 /* 1022 * The further startup procedure should be done after we leave this method 1023 * and enter the main event loop in main(), because it may result into 1024 * showing various modal dialogs that will process events from within 1025 * this method that in turn can lead to various side effects like this 1026 * window is closed before this method returns, etc. 1027 */ 1028 1029 QTimer::singleShot (0, this, SLOT (finalizeOpenView())); 1030 1031 LogFlowFuncLeave(); 1032 return true; 1033 } 1034 1035 void VBoxConsoleWnd::setMouseIntegrationLocked (bool aDisabled) 1036 { 1037 mVmDisableMouseIntegrAction->setChecked (false); 1038 mVmDisableMouseIntegrAction->setEnabled (aDisabled); 1039 } 1040 1041 /** 1042 * Shows up and activates the popup version of the main menu. 1043 * 1044 * @param aCenter If @a true, center the popup menu on the screen, otherwise 1045 * show it at the current mouse pointer location. 1046 */ 1047 void VBoxConsoleWnd::popupMainMenu (bool aCenter) 1048 { 1049 QPoint pos = QCursor::pos(); 1050 if (aCenter) 1051 { 1052 QRect deskGeo = QApplication::desktop()->screenGeometry (this); 1053 QRect popGeo = mMainMenu->frameGeometry(); 1054 popGeo.moveCenter (QPoint (deskGeo.width() / 2, deskGeo.height() / 2)); 1055 pos = popGeo.topLeft(); 1056 } 1057 else 1058 { 1059 /* put the menu's bottom right corner to the pointer's hotspot point */ 1060 pos.setX (pos.x() - mMainMenu->frameGeometry().width()); 1061 pos.setY (pos.y() - mMainMenu->frameGeometry().height()); 1062 } 1063 1064 mMainMenu->popup (pos); 1065 mMainMenu->selectFirstAction(); 1066 #ifdef Q_WS_WIN 1067 mMainMenu->activateWindow(); 1068 #endif 1069 } 1070 1071 void VBoxConsoleWnd::installGuestAdditionsFrom (const QString &aSource) 1072 { 1073 CVirtualBox vbox = vboxGlobal().virtualBox(); 1074 QString uuid; 1075 1076 CMedium image = vbox.FindDVDImage (aSource); 1077 if (image.isNull()) 1078 { 1079 image = vbox.OpenDVDImage (aSource, uuid); 1080 if (vbox.isOk()) 1081 uuid = image.GetId(); 1082 } 1083 else 1084 uuid = image.GetId(); 1085 1086 if (!vbox.isOk()) 1087 return vboxProblem().cannotOpenMedium (this, vbox, VBoxDefs::MediumType_DVD, aSource); 1088 1089 Assert (!uuid.isNull()); 1090 CMachine m = mSession.GetMachine(); 1091 1092 QString ctrName; 1093 LONG ctrPort = -1, ctrDevice = -1; 1094 /* Searching for the first suitable slot */ 1095 { 1096 CStorageControllerVector controllers = m.GetStorageControllers(); 1097 int i = 0; 1098 while (i < controllers.size() && ctrName.isNull()) 1099 { 1100 CStorageController controller = controllers [i]; 1101 CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController (controller.GetName()); 1102 int j = 0; 1103 while (j < attachments.size() && ctrName.isNull()) 581 CStorageController controller = machine.GetStorageControllerByName(attachment.GetController()); 582 if (!controller.isNull() && (attachment.GetType() == deviceType)) 583 { 584 /* Attachment menu item */ 585 QMenu *pAttachmentMenu = 0; 586 if (pMenu->menuAction()->data().toInt() > 1) 1104 587 { 1105 CMediumAttachment attachment = attachments [j]; 1106 if (attachment.GetType() == KDeviceType_DVD) 1107 { 1108 ctrName = controller.GetName(); 1109 ctrPort = attachment.GetPort(); 1110 ctrDevice = attachment.GetDevice(); 1111 } 1112 ++ j; 1113 } 1114 ++ i; 1115 } 1116 } 1117 1118 if (!ctrName.isNull()) 1119 { 1120 bool isMounted = false; 1121 1122 /* Mount medium to the predefined port/device */ 1123 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, false /* force */); 1124 if (m.isOk()) 1125 isMounted = true; 1126 else 1127 { 1128 /* Ask for force mounting */ 1129 if (vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 1130 { 1131 /* Force mount medium to the predefined port/device */ 1132 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, true /* force */); 1133 if (m.isOk()) 1134 isMounted = true; 1135 else 1136 vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, false /* retry? */); 1137 } 1138 } 1139 1140 /* Save medium mounted at runtime */ 1141 if (isMounted && mIsAutoSaveMedia) 1142 { 1143 m.SaveSettings(); 1144 if (!m.isOk()) 1145 vboxProblem().cannotSaveMachineSettings (m); 1146 } 1147 } 1148 else 1149 vboxProblem().cannotMountGuestAdditions (m.GetName()); 1150 } 1151 1152 void VBoxConsoleWnd::setMask (const QRegion &aRegion) 1153 { 1154 QRegion region = aRegion; 1155 1156 /* The global mask shift cause of toolbars and such things. */ 1157 region.translate (mMaskShift.width(), mMaskShift.height()); 1158 1159 /* Including mini toolbar area */ 1160 QRegion toolBarRegion (mMiniToolBar->mask()); 1161 toolBarRegion.translate (mMiniToolBar->mapToGlobal (toolBarRegion.boundingRect().topLeft()) - QPoint (1, 0)); 1162 region += toolBarRegion; 1163 1164 /* Restrict the drawing to the available space on the screen. 1165 * (The &operator is better than the previous used -operator, 1166 * because this excludes space around the real screen also. 1167 * This is necessary for the mac.) */ 1168 region &= mStrictedRegion; 1169 1170 #ifdef Q_WS_WIN 1171 QRegion difference = mPrevRegion.subtract (region); 1172 1173 /* Region offset calculation */ 1174 int fleft = 0, ftop = 0; 1175 1176 /* Visible region calculation */ 1177 HRGN newReg = CreateRectRgn (0, 0, 0, 0); 1178 CombineRgn (newReg, region.handle(), 0, RGN_COPY); 1179 OffsetRgn (newReg, fleft, ftop); 1180 1181 /* Invisible region calculation */ 1182 HRGN diffReg = CreateRectRgn (0, 0, 0, 0); 1183 CombineRgn (diffReg, difference.handle(), 0, RGN_COPY); 1184 OffsetRgn (diffReg, fleft, ftop); 1185 1186 /* Set the current visible region and clean the previous */ 1187 SetWindowRgn (winId(), newReg, FALSE); 1188 RedrawWindow (0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 1189 RedrawWindow (mConsole->viewport()->winId(), 0, 0, RDW_INVALIDATE); 1190 1191 mPrevRegion = region; 1192 #elif defined (Q_WS_MAC) 1193 # if defined (VBOX_GUI_USE_QUARTZ2D) 1194 if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) 1195 { 1196 /* If we are using the Quartz2D backend we have to trigger 1197 * an repaint only. All the magic clipping stuff is done 1198 * in the paint engine. */ 1199 ::darwinWindowInvalidateShape (mConsole->viewport()); 1200 } 1201 else 1202 # endif 1203 { 1204 /* This is necessary to avoid the flicker by an mask update. 1205 * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html 1206 * for the hint. 1207 * There *must* be a better solution. */ 1208 if (!region.isEmpty()) 1209 region |= QRect (0, 0, 1, 1); 1210 // /* Save the current region for later processing in the darwin event handler. */ 1211 // mCurrRegion = region; 1212 // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately 1213 // * this command flushes a copy of the backbuffer to the screen after the new 1214 // * mask is set. This leads into a missplaced drawing of the content. Currently 1215 // * no alternative to this and also this is not 100% perfect. */ 1216 // repaint(); 1217 // qApp->processEvents(); 1218 // /* Now force the reshaping of the window. This is definitly necessary. */ 1219 // ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId())); 1220 QMainWindow::setMask (region); 1221 // HIWindowInvalidateShadow (::darwinToWindowRef (mConsole->viewport())); 1222 } 1223 #else 1224 QMainWindow::setMask (region); 1225 #endif 1226 } 1227 1228 void VBoxConsoleWnd::clearMask() 1229 { 1230 #ifdef Q_WS_WIN 1231 SetWindowRgn (winId(), 0, TRUE); 1232 #else 1233 QMainWindow::clearMask(); 1234 #endif 1235 } 1236 1237 void VBoxConsoleWnd::onDisplayResize (ulong aHeight, ulong aWidth) 1238 { 1239 if (mIsSeamless && QApplication::desktop()->availableGeometry (this).size() != QSize (aHeight, aWidth)) 1240 { 1241 mVmSeamlessAction->setChecked (false); 1242 /* should be cleared already, but just in case */ 1243 if (mIsSeamless) 1244 toggleFullscreenMode (false, true); 1245 } 1246 } 1247 1248 1249 bool VBoxConsoleWnd::event (QEvent *aEvent) 1250 { 1251 switch (aEvent->type()) 1252 { 1253 /* By handling every Resize and Move we keep track of the normal 1254 * (non-minimized and non-maximized) window geometry. Shame on Qt 1255 * that it doesn't provide this geometry in its public APIs. */ 1256 1257 case QEvent::Resize: 1258 { 1259 QResizeEvent *re = (QResizeEvent *) aEvent; 1260 1261 if (!mIsWaitingModeResize && !isWindowMaximized() && 1262 !isTrueFullscreen() && !isTrueSeamless()) 1263 { 1264 mNormalGeo.setSize (re->size()); 1265 #ifdef VBOX_WITH_DEBUGGER_GUI 1266 dbgAdjustRelativePos(); 1267 #endif 1268 } 1269 1270 if (mIsWaitingModeResize) 1271 { 1272 if (!mIsFullscreen && !mIsSeamless) 1273 { 1274 mIsWaitingModeResize = false; 1275 QTimer::singleShot (0, this, SLOT (onExitFullscreen())); 1276 } 1277 } 1278 break; 1279 } 1280 case QEvent::Move: 1281 { 1282 if (!isWindowMaximized() && !isTrueFullscreen() && !isTrueSeamless()) 1283 { 1284 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1285 #ifdef VBOX_WITH_DEBUGGER_GUI 1286 dbgAdjustRelativePos(); 1287 #endif 1288 } 1289 break; 1290 } 1291 #ifdef Q_WS_MAC 1292 case QEvent::Paint: 1293 { 1294 if (mIsSeamless) 1295 { 1296 /* Clear the background */ 1297 CGContextClearRect (::darwinToCGContextRef (this), ::darwinToCGRect (frameGeometry())); 1298 } 1299 break; 1300 } 1301 #endif 1302 case StatusTipEvent::Type: 1303 { 1304 StatusTipEvent *ev = (StatusTipEvent*) aEvent; 1305 statusBar()->showMessage (ev->mTip); 1306 break; 1307 } 1308 default: 1309 break; 1310 } 1311 1312 return QMainWindow::event (aEvent); 1313 } 1314 1315 void VBoxConsoleWnd::closeEvent (QCloseEvent *aEvent) 1316 { 1317 LogFlowFuncEnter(); 1318 1319 static const char *kSave = "save"; 1320 static const char *kShutdown = "shutdown"; 1321 static const char *kPowerOff = "powerOff"; 1322 static const char *kDiscardCurState = "discardCurState"; 1323 1324 if (!mConsole) 1325 { 1326 aEvent->accept(); 1327 LogFlowFunc (("Console already destroyed!")); 1328 LogFlowFuncLeave(); 1329 return; 1330 } 1331 1332 switch (mMachineState) 1333 { 1334 case KMachineState_PoweredOff: 1335 case KMachineState_Saved: 1336 case KMachineState_Teleported: 1337 case KMachineState_Aborted: 1338 /* The machine has been already powered off or saved or aborted -- close the window immediately. */ 1339 aEvent->accept(); 1340 break; 1341 1342 default: 1343 /* The machine is in some temporary state like Saving or Stopping. 1344 * Ignore the close event. When it is Stopping, it will be soon closed anyway from updateMachineState(). 1345 * In all other cases, an appropriate progress dialog will be shown within a few seconds. */ 1346 aEvent->ignore(); 1347 break; 1348 1349 case KMachineState_Teleporting: /** @todo Live Migration: Test closing a VM that's being teleported or snapshotted. */ 1350 case KMachineState_LiveSnapshotting: 1351 case KMachineState_Running: 1352 case KMachineState_Paused: 1353 case KMachineState_TeleportingPausedVM: /** @todo Live Migration: Check out this. */ 1354 case KMachineState_Stuck: 1355 /* Start with ignoring the close event */ 1356 aEvent->ignore(); 1357 1358 bool isACPIEnabled = mSession.GetConsole().GetGuestEnteredACPIMode(); 1359 1360 bool success = true; 1361 1362 bool wasPaused = mMachineState == KMachineState_Paused 1363 || mMachineState == KMachineState_Stuck 1364 || mMachineState == KMachineState_TeleportingPausedVM; 1365 if (!wasPaused) 1366 { 1367 /* Suspend the VM and ignore the close event if failed to do so. 1368 * pause() will show the error message to the user. */ 1369 success = mConsole->pause (true); 1370 } 1371 1372 if (success) 1373 { 1374 success = false; 1375 1376 CMachine machine = mSession.GetMachine(); 1377 VBoxCloseVMDlg dlg (this); 1378 QString typeId = machine.GetOSTypeId(); 1379 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 1380 1381 /* Make the Discard checkbox invisible if there are no snapshots */ 1382 dlg.mCbDiscardCurState->setVisible (machine.GetSnapshotCount() > 0); 1383 if (!machine.GetCurrentSnapshot().isNull()) 1384 dlg.mCbDiscardCurState->setText (dlg.mCbDiscardCurState->text().arg (machine.GetCurrentSnapshot().GetName())); 1385 1386 if (mMachineState != KMachineState_Stuck) 1387 { 1388 /* Read the last user's choice for the given VM */ 1389 QStringList lastAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1390 AssertWrapperOk (machine); 1391 if (lastAction [0] == kSave) 1392 { 1393 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1394 dlg.mRbSave->setChecked (true); 1395 dlg.mRbSave->setFocus(); 1396 } 1397 else if (lastAction [0] == kPowerOff || !isACPIEnabled) 1398 { 1399 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1400 dlg.mRbPowerOff->setChecked (true); 1401 dlg.mRbPowerOff->setFocus(); 1402 } 1403 else /* The default is ACPI Shutdown */ 1404 { 1405 dlg.mRbShutdown->setChecked (true); 1406 dlg.mRbShutdown->setFocus(); 1407 } 1408 dlg.mCbDiscardCurState->setChecked (lastAction.count() > 1 && lastAction [1] == kDiscardCurState); 1409 } 1410 else 1411 { 1412 /* The stuck VM can only be powered off; disable anything else and choose PowerOff */ 1413 dlg.mRbSave->setEnabled (false); 1414 dlg.mRbShutdown->setEnabled (false); 1415 dlg.mRbPowerOff->setChecked (true); 1416 } 1417 1418 bool wasShutdown = false; 1419 1420 if (dlg.exec() == QDialog::Accepted) 1421 { 1422 /* Disable auto closure because we want to have a chance to show 1423 * the error dialog on save state / power off failure. */ 1424 mNoAutoClose = true; 1425 1426 CConsole console = mConsole->console(); 1427 1428 if (dlg.mRbSave->isChecked()) 1429 { 1430 CProgress progress = console.SaveState(); 1431 1432 if (console.isOk()) 1433 { 1434 /* Show the "VM saving" progress dialog */ 1435 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1436 if (progress.GetResultCode() != 0) 1437 vboxProblem().cannotSaveMachineState (progress); 1438 else 1439 success = true; 1440 } 1441 else 1442 vboxProblem().cannotSaveMachineState (console); 1443 } 1444 else if (dlg.mRbShutdown->isChecked()) 1445 { 1446 /* Unpause the VM to let it grab the ACPI shutdown event */ 1447 mConsole->pause (false); 1448 /* Prevent the subsequent unpause request */ 1449 wasPaused = true; 1450 /* Signal ACPI shutdown (if there is no ACPI device, the 1451 * operation will fail) */ 1452 console.PowerButton(); 1453 wasShutdown = console.isOk(); 1454 if (!wasShutdown) 1455 vboxProblem().cannotACPIShutdownMachine (console); 1456 /* Success is always false because we never accept the close 1457 * window action when doing ACPI shutdown */ 1458 success = false; 1459 } 1460 else if (dlg.mRbPowerOff->isChecked()) 1461 { 1462 CProgress progress = console.PowerDown(); 1463 1464 if (console.isOk()) 1465 { 1466 /* Show the power down progress dialog */ 1467 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1468 if (progress.GetResultCode() != 0) 1469 vboxProblem().cannotStopMachine (progress); 1470 else 1471 success = true; 1472 } 1473 else 1474 vboxProblem().cannotStopMachine (console); 1475 1476 if (success) 1477 { 1478 /* Note: leave success = true even if we fail to 1479 * discard the current state later -- the console window 1480 * will closed anyway */ 1481 1482 /* Discard the current state if requested */ 1483 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo (&dlg)) 1484 { 1485 CSnapshot snapshot = machine.GetCurrentSnapshot(); 1486 CProgress progress = console.RestoreSnapshot (snapshot); 1487 if (console.isOk()) 1488 { 1489 /* Show the progress dialog */ 1490 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1491 if (progress.GetResultCode() != 0) 1492 vboxProblem().cannotRestoreSnapshot (progress, snapshot.GetName()); 1493 } 1494 else 1495 vboxProblem().cannotRestoreSnapshot (console, snapshot.GetName()); 1496 } 1497 } 1498 } 1499 1500 if (success) 1501 { 1502 /* Accept the close action on success */ 1503 aEvent->accept(); 1504 } 1505 1506 if (success || wasShutdown) 1507 { 1508 /* Read the last user's choice for the given VM */ 1509 QStringList prevAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1510 /* Memorize the last user's choice for the given VM */ 1511 QString lastAction = kPowerOff; 1512 if (dlg.mRbSave->isChecked()) 1513 lastAction = kSave; 1514 else if (dlg.mRbShutdown->isChecked() || 1515 (dlg.mRbPowerOff->isChecked() && prevAction [0] == kShutdown && !isACPIEnabled)) 1516 lastAction = kShutdown; 1517 else if (dlg.mRbPowerOff->isChecked()) 1518 lastAction = kPowerOff; 1519 else 1520 AssertFailed(); 1521 if (dlg.mCbDiscardCurState->isChecked()) 1522 (lastAction += ",") += kDiscardCurState; 1523 machine.SetExtraData (VBoxDefs::GUI_LastCloseAction, lastAction); 1524 AssertWrapperOk (machine); 1525 } 1526 } 1527 } 1528 1529 mNoAutoClose = false; 1530 1531 if ( mMachineState == KMachineState_PoweredOff 1532 || mMachineState == KMachineState_Saved 1533 || mMachineState == KMachineState_Teleported 1534 || mMachineState == KMachineState_Aborted 1535 ) 1536 { 1537 /* The machine has been stopped while showing the Close or the Pause 1538 * failure dialog -- accept the close event immediately. */ 1539 aEvent->accept(); 1540 } 1541 else 1542 { 1543 if (!success) 1544 { 1545 /* Restore the running state if needed */ 1546 if (!wasPaused && mMachineState == KMachineState_Paused) 1547 mConsole->pause (false); 1548 } 1549 } 1550 break; 1551 } 1552 1553 if (aEvent->isAccepted()) 1554 { 1555 #ifndef VBOX_GUI_SEPARATE_VM_PROCESS 1556 vboxGlobal().selectorWnd().show(); 1557 #endif 1558 1559 /* Stop LED update timer */ 1560 mIdleTimer->stop(); 1561 mIdleTimer->disconnect (SIGNAL (timeout()), this, SLOT (updateDeviceLights())); 1562 1563 /* Hide console window */ 1564 hide(); 1565 1566 /* Save the position of the window and some options */ 1567 CMachine machine = mSession.GetMachine(); 1568 QString winPos = QString ("%1,%2,%3,%4") 1569 .arg (mNormalGeo.x()).arg (mNormalGeo.y()) 1570 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 1571 if (isWindowMaximized() || (mIsFullscreen && mWasMax) || (mIsSeamless && mWasMax)) 1572 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowPosition_Max); 1573 1574 machine.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 1575 1576 machine.SetExtraData (VBoxDefs::GUI_Fullscreen, 1577 mVmFullscreenAction->isChecked() ? "on" : "off"); 1578 machine.SetExtraData (VBoxDefs::GUI_Seamless, 1579 mVmSeamlessAction->isChecked() ? "on" : "off"); 1580 machine.SetExtraData (VBoxDefs::GUI_AutoresizeGuest, 1581 mVmAutoresizeGuestAction->isChecked() ? "on" : "off"); 1582 machine.SetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide, 1583 mMiniToolBar->isAutoHide() ? "on" : "off"); 1584 1585 #ifdef VBOX_WITH_DEBUGGER_GUI 1586 /* Close & destroy the debugger GUI */ 1587 dbgDestroy(); 1588 #endif 1589 1590 /* Make sure all events are delievered */ 1591 qApp->processEvents(); 1592 1593 /* Notify all the top-level dialogs about closing */ 1594 emit closing(); 1595 } 1596 1597 LogFlowFunc (("accepted=%d\n", aEvent->isAccepted())); 1598 LogFlowFuncLeave(); 1599 } 1600 1601 #ifdef Q_WS_X11 1602 bool VBoxConsoleWnd::x11Event (XEvent *aEvent) 1603 { 1604 /* Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut, 1605 * WindowActivate and WindowDeactivate Qt events are not properly sent 1606 * on top level window (i.e. this) deactivation. The fix is to substiute 1607 * the mode in FocusOut X11 event structure to NotifyNormal to cause 1608 * Qt to process it as desired. */ 1609 if (mConsole && aEvent->type == FocusOut) 1610 { 1611 if (aEvent->xfocus.mode == NotifyWhileGrabbed && 1612 (aEvent->xfocus.detail == NotifyAncestor || 1613 aEvent->xfocus.detail == NotifyInferior || 1614 aEvent->xfocus.detail == NotifyNonlinear)) 1615 { 1616 aEvent->xfocus.mode = NotifyNormal; 1617 } 1618 } 1619 return false; 1620 } 1621 #endif 1622 1623 /** 1624 * Sets the strings of the subwidgets using the current 1625 * language. 1626 */ 1627 void VBoxConsoleWnd::retranslateUi() 1628 { 1629 #ifdef VBOX_OSE 1630 mCaptionPrefix = tr ("VirtualBox OSE"); 1631 #else 1632 mCaptionPrefix = tr ("Sun VirtualBox"); 1633 #endif 1634 1635 #ifdef VBOX_BLEEDING_EDGE 1636 mCaptionPrefix += tr (" EXPERIMENTAL build %1r%2 - %3").arg (RTBldCfgVersion()).arg (RTBldCfgRevisionStr()).arg (VBOX_BLEEDING_EDGE); 1637 #endif 1638 /* 1639 * Note: All action shortcuts should be added to the menu text in the 1640 * form of "\tHost+<Key>" where <Key> is the shortcut key according 1641 * to regular QKeySequence rules. No translation of the "Host" word is 1642 * allowed (VBoxConsoleView relies on its spelling). setAccel() must not 1643 * be used. Unfortunately on the Mac the "host" string is silently removed 1644 * & the key is created as an global shortcut. So every e.g. F key stroke 1645 * in the vm leads to a menu call of the F entry. Mysteriously the 1646 * associated action isn't started. As a workaround the Host+<key> is 1647 * written in braces after the menu text. 1648 */ 1649 1650 /* VM actions */ 1651 #ifdef Q_WS_MAC 1652 qt_set_sequence_auto_mnemonic (false); 1653 #endif 1654 1655 mVmDisMouseIntegrMenu->setToolTip (tr ("Mouse Integration", "enable/disable...")); 1656 #if 0 /* TODO: Allow to setup status-bar! */ 1657 mVmAutoresizeMenu->setToolTip (tr ("Auto-resize Guest Display", "enable/disable...")); 1658 #endif 1659 1660 mVmFullscreenAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Fullscreen Mode"), "F")); 1661 mVmFullscreenAction->setStatusTip (tr ("Switch to fullscreen mode" )); 1662 1663 mVmSeamlessAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Seam&less Mode"), "L")); 1664 mVmSeamlessAction->setStatusTip (tr ("Switch to seamless desktop integration mode")); 1665 1666 mVmAutoresizeGuestAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Auto-resize &Guest Display"), "G")); 1667 mVmAutoresizeGuestAction->setStatusTip (tr ("Automatically resize the guest display when the " 1668 "window is resized (requires Guest Additions)")); 1669 1670 mVmAdjustWindowAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Adjust Window Size"), "A")); 1671 mVmAdjustWindowAction->setStatusTip (tr ("Adjust window size and position to best fit the guest display")); 1672 1673 /* mVmDisableMouseIntegrAction is set up in updateAppearanceOf() */ 1674 1675 mVmTypeCADAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Del"), "Del")); 1676 mVmTypeCADAction->setStatusTip (tr ("Send the Ctrl-Alt-Del sequence to the virtual machine")); 1677 1678 #if defined(Q_WS_X11) 1679 mVmTypeCABSAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Backspace"), "Backspace")); 1680 mVmTypeCABSAction->setStatusTip (tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine")); 1681 #endif 1682 1683 mVmTakeSnapshotAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Take &Snapshot..."), "S")); 1684 mVmTakeSnapshotAction->setStatusTip (tr ("Take a snapshot of the virtual machine")); 1685 1686 mVmShowInformationDlgAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Session I&nformation Dialog"), "N")); 1687 mVmShowInformationDlgAction->setStatusTip (tr ("Show Session Information Dialog")); 1688 1689 mVmResetAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Reset"), "R")); 1690 mVmResetAction->setStatusTip (tr ("Reset the virtual machine")); 1691 1692 /* mVmPauseAction is set up in updateAppearanceOf() */ 1693 1694 #ifdef Q_WS_MAC 1695 /* Host+H is Hide on the mac */ 1696 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "U")); 1697 #else /* Q_WS_MAC */ 1698 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "H")); 1699 #endif /* !Q_WS_MAC */ 1700 mVmACPIShutdownAction->setStatusTip (tr ("Send the ACPI Power Button press event to the virtual machine")); 1701 1702 mVmCloseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Close..." ), "Q")); 1703 mVmCloseAction->setStatusTip (tr ("Close the virtual machine")); 1704 mVmCloseAction->setMenuRole (QAction::QuitRole); 1705 1706 /* Devices actions */ 1707 mDevicesCDMenu->setTitle (tr ("&CD/DVD Devices")); 1708 mDevicesFDMenu->setTitle (tr ("&Floppy Devices")); 1709 1710 mDevicesNetworkDialogAction->setText (tr ("&Network Adapters...")); 1711 mDevicesNetworkDialogAction->setStatusTip (tr ("Change the settings of network adapters")); 1712 1713 mDevicesSFDialogAction->setText (tr ("&Shared Folders...")); 1714 mDevicesSFDialogAction->setStatusTip (tr ("Create or modify shared folders")); 1715 1716 mDevicesSwitchVrdpAction->setText (tr ("&Remote Display")); 1717 mDevicesSwitchVrdpAction->setStatusTip (tr ("Enable or disable remote desktop (RDP) connections to this machine")); 1718 #if 0 /* TODO: Allow to setup status-bar! */ 1719 mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server", "enable/disable...")); 1720 #endif 1721 1722 mDevicesInstallGuestToolsAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Install Guest Additions..."), "D")); 1723 mDevicesInstallGuestToolsAction->setStatusTip (tr ("Mount the Guest Additions installation image")); 1724 1725 mDevicesUSBMenu->setTitle (tr ("&USB Devices")); 1726 1727 #ifdef VBOX_WITH_DEBUGGER_GUI 1728 /* Debug actions */ 1729 if (mDbgStatisticsAction) 1730 mDbgStatisticsAction->setText (tr ("&Statistics...", "debug action")); 1731 if (mDbgCommandLineAction) 1732 mDbgCommandLineAction->setText (tr ("&Command Line...", "debug action")); 1733 if (mDbgLoggingAction) 1734 mDbgLoggingAction->setText (tr ("&Logging...", "debug action")); 1735 #endif 1736 1737 /* Help actions */ 1738 mHelpActions.retranslateUi(); 1739 1740 /* Main menu & seamless popup menu */ 1741 mVMMenu->setTitle (tr ("&Machine")); 1742 // mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png")); 1743 1744 mVMMenuMini->setTitle (tr ("&Machine")); 1745 1746 mDevicesMenu->setTitle (tr ("&Devices")); 1747 // mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png")); 1748 1749 #ifdef VBOX_WITH_DEBUGGER_GUI 1750 if (vboxGlobal().isDebuggerEnabled()) 1751 mDbgMenu->setTitle (tr ("De&bug")); 1752 #endif 1753 mHelpMenu->setTitle (tr ("&Help")); 1754 // mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png")); 1755 1756 /* Status bar widgets */ 1757 mMouseLed->setToolTip ( 1758 tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>" 1759 "<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>" 1760 "<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>" 1761 "<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>" 1762 "<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>" 1763 "<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>" 1764 "Note that the mouse integration feature requires Guest Additions to be installed in the guest OS.")); 1765 mHostkeyLed->setToolTip ( 1766 tr ("Indicates whether the keyboard is captured by the guest OS " 1767 "(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>).")); 1768 mHostkeyName->setToolTip ( 1769 tr ("Shows the currently assigned Host key.<br>" 1770 "This key, when pressed alone, toggles the keyboard and mouse " 1771 "capture state. It can also be used in combination with other keys " 1772 "to quickly perform actions from the main menu.")); 1773 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 1774 1775 #if 0 /* TODO: Allow to setup status-bar! */ 1776 mAutoresizeLed->setToolTip ( 1777 tr ("Indicates whether the guest display auto-resize function is On " 1778 "(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). " 1779 "Note that this function requires Guest Additions to be installed in the guest OS.")); 1780 #endif 1781 1782 updateAppearanceOf (AllStuff); 1783 } 1784 1785 void VBoxConsoleWnd::finalizeOpenView() 1786 { 1787 LogFlowFuncEnter(); 1788 1789 /* Notify the console scroll-view about the console-window is opened. */ 1790 mConsole->onViewOpened(); 1791 1792 bool saved = mMachineState == KMachineState_Saved; 1793 1794 CMachine machine = mSession.GetMachine(); 1795 CConsole console = mConsole->console(); 1796 1797 if (mIsFirstTimeStarted) 1798 { 1799 UIFirstRunWzd wzd (this, machine); 1800 wzd.exec(); 1801 1802 /* Remove GUI_FirstRun extra data key from the machine settings 1803 * file after showing the wizard once. */ 1804 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 1805 } 1806 1807 /* Start the VM */ 1808 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 1809 console.PowerUpPaused() : console.PowerUp(); 1810 1811 /* Check for an immediate failure */ 1812 if (!console.isOk()) 1813 { 1814 vboxProblem().cannotStartMachine (console); 1815 /* close this window (this will call closeView()) */ 1816 close(); 1817 1818 LogFlowFunc (("Error starting VM\n")); 1819 LogFlowFuncLeave(); 1820 return; 1821 } 1822 1823 mConsole->attach(); 1824 1825 /* Disable auto closure because we want to have a chance to show the 1826 * error dialog on startup failure */ 1827 mNoAutoClose = true; 1828 1829 /* show the "VM starting / restoring" progress dialog */ 1830 1831 if (saved) 1832 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1833 else 1834 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1835 1836 if (progress.GetResultCode() != 0) 1837 { 1838 vboxProblem().cannotStartMachine (progress); 1839 /* close this window (this will call closeView()) */ 1840 close(); 1841 1842 LogFlowFunc (("Error starting VM\n")); 1843 LogFlowFuncLeave(); 1844 return; 1845 } 1846 1847 mNoAutoClose = false; 1848 1849 /* Check if we missed a really quick termination after successful 1850 * startup, and process it if we did. */ 1851 if ( mMachineState == KMachineState_PoweredOff 1852 || mMachineState == KMachineState_Saved 1853 || mMachineState == KMachineState_Teleported 1854 || mMachineState == KMachineState_Aborted 1855 ) 1856 { 1857 close(); 1858 LogFlowFuncLeave(); 1859 return; 1860 } 1861 1862 /* Currently the machine is started and the guest API could be used... 1863 * Checking if the fullscreen mode should be activated */ 1864 QString str = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 1865 if (str == "on") 1866 mVmFullscreenAction->setChecked (true); 1867 1868 /* If seamless mode should be enabled then check if it is enabled 1869 * currently and re-enable it if seamless is supported */ 1870 if (mVmSeamlessAction->isChecked() && mIsSeamlessSupported && mIsGraphicsSupported) 1871 toggleFullscreenMode (true, true); 1872 #ifdef VBOX_WITH_DEBUGGER_GUI 1873 /* Open the debugger in "full screen" mode requested by the user. */ 1874 else if (vboxGlobal().isDebuggerAutoShowEnabled()) 1875 { 1876 /* console in upper left corner of the desktop. */ 1877 QRect rct (0, 0, 0, 0); 1878 QDesktopWidget *desktop = QApplication::desktop(); 1879 if (desktop) 1880 rct = desktop->availableGeometry(pos()); 1881 move (QPoint (rct.x(), rct.y())); 1882 1883 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled()) 1884 dbgShowStatistics(); 1885 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled()) 1886 dbgShowCommandLine(); 1887 1888 if (!vboxGlobal().isStartPausedEnabled()) 1889 mConsole->pause (false); 1890 } 1891 #endif 1892 1893 mIsOpenViewFinished = true; 1894 LogFlowFuncLeave(); 1895 1896 #ifdef VBOX_WITH_UPDATE_REQUEST 1897 vboxGlobal().showUpdateDialog (false /* aForce */); 1898 #endif 1899 1900 /* Finally check the status of required features. */ 1901 checkRequiredFeatures(); 1902 1903 /* Re-request all the static values finally after 1904 * view is really opened and attached. */ 1905 updateAppearanceOf (VirtualizationStuff); 1906 } 1907 1908 /** 1909 * Helper to safely close the main console window. 1910 * 1911 * This method ensures that close() will not be called if there is some 1912 * modal widget currently being executed, as it can cause uninitialization 1913 * at the point of code where it is not expected at all (example: 1914 * VBoxConsoleView::mouseEvent() calling 1915 * VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to 1916 * close the current modal widget is done and tryClose() is rescheduled for 1917 * later execution using a single-shot zero timer. 1918 * 1919 * In particular, this method is used by updateMachineState() when the VM 1920 * goes offline, which can even happen if we are inside the modal event loop, 1921 * (for example, the VM has been externally powered off or the guest OS 1922 * has initiated a shutdown procedure). 1923 */ 1924 void VBoxConsoleWnd::tryClose() 1925 { 1926 /* First close any open modal & popup widgets. Use a single shot with 1927 * timeout 0 to allow the widgets to cleany close and test then again. If 1928 * all open widgets are closed destroy ourself. */ 1929 QWidget *widget = QApplication::activeModalWidget() ? 1930 QApplication::activeModalWidget() : 1931 QApplication::activePopupWidget() ? 1932 QApplication::activePopupWidget() : 0; 1933 if (widget) 1934 { 1935 widget->close(); 1936 QTimer::singleShot (0, this, SLOT (tryClose())); 1937 } 1938 else 1939 close(); 1940 } 1941 1942 void VBoxConsoleWnd::vmFullscreen (bool aOn) 1943 { 1944 bool ok = toggleFullscreenMode (aOn, false /* aSeamless */); 1945 if (!ok) 1946 { 1947 /* On failure, restore the previous button state */ 1948 mVmFullscreenAction->blockSignals (true); 1949 mVmFullscreenAction->setChecked (!aOn); 1950 mVmFullscreenAction->blockSignals (false); 1951 } 1952 } 1953 1954 void VBoxConsoleWnd::vmSeamless (bool aOn) 1955 { 1956 /* Check if it is possible to enter/leave seamless mode */ 1957 if ((mIsSeamlessSupported && mIsGraphicsSupported) || !aOn) 1958 { 1959 bool ok = toggleFullscreenMode (aOn, true /* aSeamless */); 1960 if (!ok) 1961 { 1962 /* On failure, restore the previous button state */ 1963 mVmSeamlessAction->blockSignals (true); 1964 mVmSeamlessAction->setChecked (!aOn); 1965 mVmSeamlessAction->blockSignals (false); 1966 } 1967 } 1968 } 1969 1970 void VBoxConsoleWnd::vmAutoresizeGuest (bool on) 1971 { 1972 if (!mConsole) 1973 return; 1974 1975 #if 0 /* TODO: Allow to setup status-bar! */ 1976 mAutoresizeLed->setState (on ? 3 : 1); 1977 #endif 1978 1979 mConsole->setAutoresizeGuest (on); 1980 } 1981 1982 void VBoxConsoleWnd::vmAdjustWindow() 1983 { 1984 if (mConsole) 1985 { 1986 if (isWindowMaximized()) 1987 showNormal(); 1988 mConsole->normalizeGeometry (true /* adjustPosition */); 1989 } 1990 } 1991 1992 void VBoxConsoleWnd::vmDisableMouseIntegration (bool aOff) 1993 { 1994 if (mConsole) 1995 { 1996 mConsole->setMouseIntegrationEnabled (!aOff); 1997 updateAppearanceOf (DisableMouseIntegrAction); 1998 } 1999 } 2000 2001 void VBoxConsoleWnd::vmTypeCAD() 2002 { 2003 if (mConsole) 2004 { 2005 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2006 Assert (!keyboard.isNull()); 2007 keyboard.PutCAD(); 2008 AssertWrapperOk (keyboard); 2009 } 2010 } 2011 2012 #ifdef Q_WS_X11 2013 void VBoxConsoleWnd::vmTypeCABS() 2014 { 2015 if (mConsole) 2016 { 2017 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2018 Assert (!keyboard.isNull()); 2019 static QVector <LONG> sSequence (6); 2020 sSequence[0] = 0x1d; // Ctrl down 2021 sSequence[1] = 0x38; // Alt down 2022 sSequence[2] = 0x0E; // Backspace down 2023 sSequence[3] = 0x8E; // Backspace up 2024 sSequence[4] = 0xb8; // Alt up 2025 sSequence[5] = 0x9d; // Ctrl up 2026 keyboard.PutScancodes (sSequence); 2027 AssertWrapperOk (keyboard); 2028 } 2029 } 2030 #endif 2031 2032 void VBoxConsoleWnd::vmTakeSnapshot() 2033 { 2034 AssertReturn (mConsole, (void) 0); 2035 2036 /* remember the paused state */ 2037 bool wasPaused = mMachineState == KMachineState_Paused; 2038 if (!wasPaused) 2039 { 2040 /* Suspend the VM and ignore the close event if failed to do so. 2041 * pause() will show the error message to the user. */ 2042 if (!mConsole->pause (true)) 2043 return; 2044 } 2045 2046 CMachine machine = mSession.GetMachine(); 2047 2048 VBoxTakeSnapshotDlg dlg (this, machine); 2049 2050 QString typeId = machine.GetOSTypeId(); 2051 dlg.mLbIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 2052 2053 /* search for the max available filter index */ 2054 QString nameTemplate = tr ("Snapshot %1"); 2055 int maxSnapshotIndex = searchMaxSnapshotIndex (machine, machine.GetSnapshot (QString()), nameTemplate); 2056 dlg.mLeName->setText (nameTemplate.arg (++ maxSnapshotIndex)); 2057 2058 if (dlg.exec() == QDialog::Accepted) 2059 { 2060 CConsole console = mSession.GetConsole(); 2061 2062 CProgress progress = console.TakeSnapshot (dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 2063 2064 if (console.isOk()) 2065 { 2066 /* Show the "Taking Snapshot" progress dialog */ 2067 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 2068 2069 if (progress.GetResultCode() != 0) 2070 vboxProblem().cannotTakeSnapshot (progress); 2071 } 2072 else 2073 vboxProblem().cannotTakeSnapshot (console); 2074 } 2075 2076 /* Restore the running state if needed */ 2077 if (!wasPaused) 2078 mConsole->pause (false); 2079 } 2080 2081 void VBoxConsoleWnd::vmShowInfoDialog() 2082 { 2083 VBoxVMInformationDlg::createInformationDlg (mSession, mConsole); 2084 } 2085 2086 void VBoxConsoleWnd::vmReset() 2087 { 2088 if (mConsole) 2089 { 2090 if (vboxProblem().confirmVMReset (this)) 2091 mConsole->console().Reset(); 2092 } 2093 } 2094 2095 void VBoxConsoleWnd::vmPause (bool aOn) 2096 { 2097 if (mConsole) 2098 { 2099 mConsole->pause (aOn); 2100 updateAppearanceOf (PauseAction); 2101 } 2102 } 2103 2104 void VBoxConsoleWnd::vmACPIShutdown() 2105 { 2106 if (!mSession.GetConsole().GetGuestEnteredACPIMode()) 2107 return vboxProblem().cannotSendACPIToMachine(); 2108 2109 if (mConsole) 2110 { 2111 CConsole console = mConsole->console(); 2112 console.PowerButton(); 2113 if (!console.isOk()) 2114 vboxProblem().cannotACPIShutdownMachine (console); 2115 } 2116 } 2117 2118 void VBoxConsoleWnd::vmClose() 2119 { 2120 if (mConsole) 2121 close(); 2122 } 2123 2124 void VBoxConsoleWnd::devicesSwitchVrdp (bool aOn) 2125 { 2126 if (!mConsole) return; 2127 2128 CVRDPServer vrdpServer = mSession.GetMachine().GetVRDPServer(); 2129 /* This method should not be executed if vrdpServer is null */ 2130 Assert (!vrdpServer.isNull()); 2131 2132 vrdpServer.SetEnabled (aOn); 2133 updateAppearanceOf (VRDPStuff); 2134 } 2135 2136 void VBoxConsoleWnd::devicesOpenNetworkDialog() 2137 { 2138 if (!mConsole) return; 2139 2140 VBoxNetworkDialog dlg (mConsole, mSession); 2141 dlg.exec(); 2142 } 2143 2144 void VBoxConsoleWnd::devicesOpenSFDialog() 2145 { 2146 if (!mConsole) return; 2147 2148 VBoxSFDialog dlg (mConsole, mSession); 2149 dlg.exec(); 2150 } 2151 2152 void VBoxConsoleWnd::devicesInstallGuestAdditions() 2153 { 2154 char szAppPrivPath [RTPATH_MAX]; 2155 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); 2156 AssertRC (rc); 2157 2158 QString src1 = QString (szAppPrivPath) + "/VBoxGuestAdditions.iso"; 2159 QString src2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 2160 2161 /* Check the standard image locations */ 2162 if (QFile::exists (src1)) 2163 return installGuestAdditionsFrom (src1); 2164 else if (QFile::exists (src2)) 2165 return installGuestAdditionsFrom (src2); 2166 2167 /* Check for the already registered image */ 2168 CVirtualBox vbox = vboxGlobal().virtualBox(); 2169 QString name = QString ("VBoxGuestAdditions_%1.iso").arg (vbox.GetVersion().remove ("_OSE")); 2170 2171 CMediumVector vec = vbox.GetDVDImages(); 2172 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 2173 { 2174 QString path = it->GetLocation(); 2175 /* Compare the name part ignoring the file case */ 2176 QString fn = QFileInfo (path).fileName(); 2177 if (RTPathCompare (name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 2178 return installGuestAdditionsFrom (path); 2179 } 2180 2181 /* Download the required image */ 2182 int result = vboxProblem().cannotFindGuestAdditions ( 2183 QDir::toNativeSeparators (src1), QDir::toNativeSeparators (src2)); 2184 if (result == QIMessageBox::Yes) 2185 { 2186 QString source = QString ("http://download.virtualbox.org/virtualbox/%1/") 2187 .arg (vbox.GetVersion().remove ("_OSE")) + name; 2188 QString target = QDir (vboxGlobal().virtualBox().GetHomeFolder()) 2189 .absoluteFilePath (name); 2190 2191 VBoxAdditionsDownloader *dl = 2192 new VBoxAdditionsDownloader (source, target, mDevicesInstallGuestToolsAction); 2193 statusBar()->addWidget (dl, 0); 2194 dl->start(); 2195 } 2196 } 2197 2198 void VBoxConsoleWnd::prepareStorageMenu() 2199 { 2200 QMenu *menu = qobject_cast <QMenu*> (sender()); 2201 Assert (menu); 2202 menu->clear(); 2203 2204 KDeviceType deviceType = menu == mDevicesCDMenu ? KDeviceType_DVD : 2205 menu == mDevicesFDMenu ? KDeviceType_Floppy : 2206 KDeviceType_Null; 2207 Assert (deviceType != KDeviceType_Null); 2208 2209 VBoxDefs::MediumType mediumType = menu == mDevicesCDMenu ? VBoxDefs::MediumType_DVD : 2210 menu == mDevicesFDMenu ? VBoxDefs::MediumType_Floppy : 2211 VBoxDefs::MediumType_Invalid; 2212 Assert (mediumType != VBoxDefs::MediumType_Invalid); 2213 2214 CMachine machine = mSession.GetMachine(); 2215 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 2216 foreach (const CMediumAttachment &attachment, attachments) 2217 { 2218 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 2219 if ( !controller.isNull() 2220 && (attachment.GetType() == deviceType)) 2221 { 2222 /* Attachment menu item */ 2223 QMenu *attachmentMenu = 0; 2224 if (menu->menuAction()->data().toInt() > 1) 2225 { 2226 attachmentMenu = new QMenu (menu); 2227 attachmentMenu->setTitle (QString ("%1 (%2)").arg (controller.GetName()) 2228 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), 2229 attachment.GetPort(), 2230 attachment.GetDevice())))); 588 pAttachmentMenu = new QMenu(pMenu); 589 pAttachmentMenu->setTitle(QString("%1 (%2)").arg(controller.GetName()) 590 .arg (vboxGlobal().toString(StorageSlot(controller.GetBus(), 591 attachment.GetPort(), 592 attachment.GetDevice())))); 2231 593 switch (controller.GetBus()) 2232 594 { 2233 595 case KStorageBus_IDE: 2234 attachmentMenu->setIcon (QIcon(":/ide_16px.png")); break;596 pAttachmentMenu->setIcon(QIcon(":/ide_16px.png")); break; 2235 597 case KStorageBus_SATA: 2236 attachmentMenu->setIcon (QIcon(":/sata_16px.png")); break;598 pAttachmentMenu->setIcon(QIcon(":/sata_16px.png")); break; 2237 599 case KStorageBus_SCSI: 2238 attachmentMenu->setIcon (QIcon(":/scsi_16px.png")); break;600 pAttachmentMenu->setIcon(QIcon(":/scsi_16px.png")); break; 2239 601 case KStorageBus_Floppy: 2240 attachmentMenu->setIcon (QIcon(":/floppy_16px.png")); break;602 pAttachmentMenu->setIcon(QIcon(":/floppy_16px.png")); break; 2241 603 default: 2242 604 break; 2243 605 } 2244 menu->addMenu (attachmentMenu);606 pMenu->addMenu(pAttachmentMenu); 2245 607 } 2246 else attachmentMenu = menu;608 else pAttachmentMenu = pMenu; 2247 609 2248 610 /* Mount Medium actions */ … … 2290 652 currentUsed = true; 2291 653 2292 QAction *mountMediumAction = new QAction (VBoxMedium (medium, mediumType).name(), attachmentMenu);2293 mountMediumAction->setCheckable 2294 mountMediumAction->setChecked 2295 mountMediumAction->setData (QVariant::fromValue (MountTarget(controller.GetName(),2296 2297 2298 2299 connect (mountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium()));2300 attachmentMenu->addAction(mountMediumAction);654 QAction *mountMediumAction = new QAction(VBoxMedium(medium, mediumType).name(), pAttachmentMenu); 655 mountMediumAction->setCheckable(true); 656 mountMediumAction->setChecked(!currentMedium.isNull() && medium.GetId() == currentId); 657 mountMediumAction->setData(QVariant::fromValue(MountTarget(controller.GetName(), 658 attachment.GetPort(), 659 attachment.GetDevice(), 660 medium.GetId()))); 661 connect(mountMediumAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium())); 662 pAttachmentMenu->addAction(mountMediumAction); 2301 663 ++ mediumsToBeShown; 2302 664 if (mediumsToBeShown == maxMediumsToBeShown) … … 2306 668 2307 669 /* Virtual Media Manager action */ 2308 QAction *callVMMAction = new QAction (attachmentMenu);2309 callVMMAction->setIcon (QIcon(":/diskimage_16px.png"));2310 callVMMAction->setData (QVariant::fromValue (MountTarget(controller.GetName(),2311 2312 2313 2314 connect (callVMMAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium()));2315 attachmentMenu->addAction(callVMMAction);670 QAction *callVMMAction = new QAction(pAttachmentMenu); 671 callVMMAction->setIcon(QIcon(":/diskimage_16px.png")); 672 callVMMAction->setData(QVariant::fromValue(MountTarget(controller.GetName(), 673 attachment.GetPort(), 674 attachment.GetDevice(), 675 mediumType))); 676 connect(callVMMAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium())); 677 pAttachmentMenu->addAction(callVMMAction); 2316 678 2317 679 /* Separator */ 2318 attachmentMenu->addSeparator();680 pAttachmentMenu->addSeparator(); 2319 681 2320 682 /* Unmount Medium action */ 2321 QAction *unmountMediumAction = new QAction (attachmentMenu);2322 unmountMediumAction->setEnabled 2323 unmountMediumAction->setData (QVariant::fromValue (MountTarget(controller.GetName(),2324 2325 2326 connect (unmountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium()));2327 attachmentMenu->addAction(unmountMediumAction);683 QAction *unmountMediumAction = new QAction(pAttachmentMenu); 684 unmountMediumAction->setEnabled(!currentMedium.isNull()); 685 unmountMediumAction->setData(QVariant::fromValue(MountTarget(controller.GetName(), 686 attachment.GetPort(), 687 attachment.GetDevice()))); 688 connect(unmountMediumAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium())); 689 pAttachmentMenu->addAction(unmountMediumAction); 2328 690 2329 691 /* Switch CD/FD naming */ … … 2331 693 { 2332 694 case VBoxDefs::MediumType_DVD: 2333 callVMMAction->setText (tr("More CD/DVD Images..."));2334 unmountMediumAction->setText (tr("Unmount CD/DVD Device"));2335 unmountMediumAction->setIcon (VBoxGlobal::iconSet(":/cd_unmount_16px.png",2336 695 callVMMAction->setText(tr("More CD/DVD Images...")); 696 unmountMediumAction->setText(tr("Unmount CD/DVD Device")); 697 unmountMediumAction->setIcon(VBoxGlobal::iconSet(":/cd_unmount_16px.png", 698 ":/cd_unmount_dis_16px.png")); 2337 699 break; 2338 700 case VBoxDefs::MediumType_Floppy: 2339 callVMMAction->setText (tr("More Floppy Images..."));2340 unmountMediumAction->setText (tr("Unmount Floppy Device"));2341 unmountMediumAction->setIcon (VBoxGlobal::iconSet(":/fd_unmount_16px.png",2342 701 callVMMAction->setText(tr("More Floppy Images...")); 702 unmountMediumAction->setText(tr("Unmount Floppy Device")); 703 unmountMediumAction->setIcon(VBoxGlobal::iconSet(":/fd_unmount_16px.png", 704 ":/fd_unmount_dis_16px.png")); 2343 705 break; 2344 706 default: … … 2348 710 } 2349 711 2350 if ( menu->menuAction()->data().toInt() == 0)712 if (pMenu->menuAction()->data().toInt() == 0) 2351 713 { 2352 714 /* Empty menu item */ 2353 Assert (menu->isEmpty());2354 QAction *emptyMenuAction = new QAction (menu);2355 emptyMenuAction->setEnabled 715 Assert(pMenu->isEmpty()); 716 QAction *emptyMenuAction = new QAction(pMenu); 717 emptyMenuAction->setEnabled(false); 2356 718 switch (mediumType) 2357 719 { 2358 720 case VBoxDefs::MediumType_DVD: 2359 emptyMenuAction->setText (tr("No CD/DVD Devices Attached"));721 emptyMenuAction->setText(tr("No CD/DVD Devices Attached")); 2360 722 break; 2361 723 case VBoxDefs::MediumType_Floppy: 2362 emptyMenuAction->setText (tr("No Floppy Devices Attached"));724 emptyMenuAction->setText(tr("No Floppy Devices Attached")); 2363 725 break; 2364 726 default: 2365 727 break; 2366 728 } 2367 emptyMenuAction->setIcon (VBoxGlobal::iconSet (":/delete_16px.png", ":/delete_dis_16px.png")); 2368 menu->addAction (emptyMenuAction); 2369 } 2370 } 2371 2372 void VBoxConsoleWnd::prepareNetworkMenu() 2373 { 2374 mDevicesNetworkMenu->clear(); 2375 mDevicesNetworkMenu->addAction (mDevicesNetworkDialogAction); 2376 } 2377 2378 void VBoxConsoleWnd::prepareSFMenu() 2379 { 2380 mDevicesSFMenu->clear(); 2381 mDevicesSFMenu->addAction (mDevicesSFDialogAction); 2382 } 2383 2384 void VBoxConsoleWnd::mountMedium() 729 emptyMenuAction->setIcon(VBoxGlobal::iconSet(":/delete_16px.png", ":/delete_dis_16px.png")); 730 pMenu->addAction(emptyMenuAction); 731 } 732 } 733 734 void UIMachineLogic::sltMountStorageMedium() 2385 735 { 2386 736 /* Get sender action */ 2387 QAction *action = qobject_cast <QAction*>(sender());2388 Assert (action);737 QAction *action = qobject_cast<QAction*>(sender()); 738 AssertMsg(action, ("This slot should only be called on selecting storage menu item!\n")); 2389 739 2390 740 /* Get current machine */ 2391 CMachine machine = mSession.GetMachine();741 CMachine machine = session().GetMachine(); 2392 742 2393 743 /* Get mount-target */ 2394 MountTarget target = action->data().value 744 MountTarget target = action->data().value<MountTarget>(); 2395 745 2396 746 /* Current mount-target attributes */ 2397 CMediumAttachment currentAttachment = machine.GetMediumAttachment 747 CMediumAttachment currentAttachment = machine.GetMediumAttachment(target.name, target.port, target.device); 2398 748 CMedium currentMedium = currentAttachment.GetMedium(); 2399 QString currentId = currentMedium.isNull() ? QString 749 QString currentId = currentMedium.isNull() ? QString("") : currentMedium.GetId(); 2400 750 2401 751 /* New mount-target attributes */ 2402 QString newId = QString 752 QString newId = QString(""); 2403 753 bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid; 2404 754 … … 2415 765 } 2416 766 /* Open VMM Dialog */ 2417 VBoxMediaManagerDlg dlg (this);2418 dlg.setup 767 VBoxMediaManagerDlg dlg(machineWindowWrapper()->machineWindow()); 768 dlg.setup(target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages); 2419 769 if (dlg.exec() == QDialog::Accepted) 2420 770 newId = dlg.selectedId(); … … 2429 779 /* Remount medium to the predefined port/device */ 2430 780 bool wasMounted = false; 2431 machine.MountMedium 781 machine.MountMedium(target.name, target.port, target.device, newId, false /* force */); 2432 782 if (machine.isOk()) 2433 783 wasMounted = true; … … 2435 785 { 2436 786 /* Ask for force remounting */ 2437 if (vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok)787 if (vboxProblem().cannotRemountMedium(machineWindowWrapper()->machineWindow(), machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok) 2438 788 { 2439 789 /* Force remount medium to the predefined port/device. */ 2440 machine.MountMedium 790 machine.MountMedium(target.name, target.port, target.device, newId, true /* force */); 2441 791 if (machine.isOk()) 2442 792 wasMounted = true; 2443 793 else 2444 vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */);794 vboxProblem().cannotRemountMedium(machineWindowWrapper()->machineWindow(), machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */); 2445 795 } 2446 796 } 2447 797 2448 798 /* Save medium mounted at runtime */ 2449 if (wasMounted && m IsAutoSaveMedia)799 if (wasMounted && m_bIsAutoSaveMedia) 2450 800 { 2451 801 machine.SaveSettings(); 2452 802 if (!machine.isOk()) 2453 vboxProblem().cannotSaveMachineSettings (machine); 2454 } 2455 } 2456 2457 /** 2458 * Attach/Detach selected USB Device. 2459 */ 2460 void VBoxConsoleWnd::switchUSB (QAction *aAction) 2461 { 2462 if (!mConsole) return; 2463 2464 CConsole console = mSession.GetConsole(); 2465 AssertWrapperOk (mSession); 2466 2467 CUSBDevice usb = mDevicesUSBMenu->getUSB (aAction); 2468 /* if null then some other item but a USB device is selected */ 2469 if (usb.isNull()) 803 vboxProblem().cannotSaveMachineSettings(machine); 804 } 805 } 806 807 void UIMachineLogic::sltOpenNetworkAdaptersDialog() 808 { 809 if (!machineWindowWrapper()) 2470 810 return; 2471 811 2472 if (!aAction->isChecked()) 2473 { 2474 console.DetachUSBDevice (usb.GetId()); 2475 if (!console.isOk()) 2476 { 2477 /// @todo (r=dmik) the dialog should be either modeless 2478 // or we have to pause the VM 2479 vboxProblem().cannotDetachUSBDevice (console, vboxGlobal().details (usb)); 2480 } 2481 } 2482 else 2483 { 2484 console.AttachUSBDevice (usb.GetId()); 2485 if (!console.isOk()) 2486 { 2487 /// @todo (r=dmik) the dialog should be either modeless 2488 // or we have to pause the VM 2489 vboxProblem().cannotAttachUSBDevice (console, vboxGlobal().details (usb)); 2490 } 2491 } 2492 } 2493 2494 void VBoxConsoleWnd::showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent) 2495 { 2496 if (aInd == mCDLed) 2497 { 2498 mDevicesCDMenu->exec (aEvent->globalPos()); 2499 } 2500 #if 0 /* TODO: Allow to setup status-bar! */ 2501 else if (aInd == mFDLed) 2502 { 2503 mDevicesFDMenu->exec (aEvent->globalPos()); 2504 } 2505 #endif 2506 else if (aInd == mNetLed) 2507 { 2508 if (mDevicesNetworkMenu->isEnabled()) 2509 mDevicesNetworkMenu->exec (aEvent->globalPos()); 2510 } 2511 else if (aInd == mUSBLed) 2512 { 2513 if (mDevicesUSBMenu->isEnabled()) 2514 mDevicesUSBMenu->exec (aEvent->globalPos()); 2515 } 2516 else if (aInd == mSFLed) 2517 { 2518 if (mDevicesSFMenu->isEnabled()) 2519 mDevicesSFMenu->exec (aEvent->globalPos()); 2520 } 2521 else if (aInd == mMouseLed) 2522 { 2523 mVmDisMouseIntegrMenu->exec (aEvent->globalPos()); 2524 } 2525 #if 0 /* TODO: Allow to setup status-bar! */ 2526 else if (aInd == mVrdpLed) 2527 { 2528 mDevicesVRDPMenu->exec (aEvent->globalPos()); 2529 } 2530 else if (aInd == mAutoresizeLed) 2531 { 2532 mVmAutoresizeMenu->exec (aEvent->globalPos()); 2533 } 2534 #endif 2535 } 2536 2537 void VBoxConsoleWnd::updateDeviceLights() 2538 { 2539 if (mConsole) 2540 { 2541 CConsole &console = mConsole->console(); 2542 int st; 2543 if (mHDLed->state() != KDeviceActivity_Null) 2544 { 2545 st = console.GetDeviceActivity (KDeviceType_HardDisk); 2546 if (mHDLed->state() != st) 2547 mHDLed->setState (st); 2548 } 2549 if (mCDLed->state() != KDeviceActivity_Null) 2550 { 2551 st = console.GetDeviceActivity (KDeviceType_DVD); 2552 if (mCDLed->state() != st) 2553 mCDLed->setState (st); 2554 } 2555 #if 0 /* TODO: Allow to setup status-bar! */ 2556 if (mFDLed->state() != KDeviceActivity_Null) 2557 { 2558 st = console.GetDeviceActivity (KDeviceType_Floppy); 2559 if (mFDLed->state() != st) 2560 mFDLed->setState (st); 2561 } 2562 #endif 2563 if (mNetLed->state() != KDeviceActivity_Null) 2564 { 2565 st = console.GetDeviceActivity (KDeviceType_Network); 2566 if (mNetLed->state() != st) 2567 mNetLed->setState (st); 2568 } 2569 if (mUSBLed->state() != KDeviceActivity_Null) 2570 { 2571 st = console.GetDeviceActivity (KDeviceType_USB); 2572 if (mUSBLed->state() != st) 2573 mUSBLed->setState (st); 2574 } 2575 if (mSFLed->state() != KDeviceActivity_Null) 2576 { 2577 st = console.GetDeviceActivity (KDeviceType_SharedFolder); 2578 if (mSFLed->state() != st) 2579 mSFLed->setState (st); 2580 } 2581 } 2582 } 2583 2584 void VBoxConsoleWnd::updateMachineState (KMachineState aState) 2585 { 2586 bool guruMeditation = false; 2587 2588 if (mConsole && mMachineState != aState) 2589 { 2590 switch (aState) 812 UINetworkAdaptersDialog dlg(machineWindowWrapper()->machineWindow(), session()); 813 dlg.exec(); 814 } 815 816 void UIMachineLogic::sltOpenSharedFoldersDialog() 817 { 818 if (!machineWindowWrapper()) 819 return; 820 821 UISharedFoldersDialog dlg(machineWindowWrapper()->machineWindow(), session()); 822 dlg.exec(); 823 } 824 825 void UIMachineLogic::sltPrepareUSBMenu() 826 { 827 } 828 829 void UIMachineLogic::sltAttachUSBDevice() 830 { 831 } 832 833 void UIMachineLogic::sltSwitchVrdp(bool aOn) 834 { 835 if (!machineWindowWrapper()) 836 return; 837 838 CVRDPServer server = session().GetMachine().GetVRDPServer(); 839 AssertMsg(!server.isNull(), ("VRDP Server should not be null!\n")); 840 841 server.SetEnabled(aOn); 842 843 updateAppearanceOf(UIVisualElement_VRDPStuff); 844 } 845 846 void UIMachineLogic::sltInstallGuestAdditions() 847 { 848 if (!machineWindowWrapper()) 849 return; 850 851 char strAppPrivPath[RTPATH_MAX]; 852 int rc = RTPathAppPrivateNoArch(strAppPrivPath, sizeof(strAppPrivPath)); 853 AssertRC (rc); 854 855 QString strSrc1 = QString(strAppPrivPath) + "/VBoxGuestAdditions.iso"; 856 QString strSrc2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 857 858 /* Check the standard image locations */ 859 if (QFile::exists(strSrc1)) 860 return installGuestAdditionsFrom(strSrc1); 861 else if (QFile::exists(strSrc2)) 862 return installGuestAdditionsFrom(strSrc2); 863 864 /* Check for the already registered image */ 865 CVirtualBox vbox = vboxGlobal().virtualBox(); 866 QString name = QString("VBoxGuestAdditions_%1.iso").arg(vbox.GetVersion().remove("_OSE")); 867 868 CMediumVector vec = vbox.GetDVDImages(); 869 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 870 { 871 QString path = it->GetLocation(); 872 /* Compare the name part ignoring the file case */ 873 QString fn = QFileInfo(path).fileName(); 874 if (RTPathCompare(name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 875 return installGuestAdditionsFrom(path); 876 } 877 878 /* Download the required image */ 879 int result = vboxProblem().cannotFindGuestAdditions(QDir::toNativeSeparators(strSrc1), QDir::toNativeSeparators(strSrc2)); 880 if (result == QIMessageBox::Yes) 881 { 882 QString source = QString("http://download.virtualbox.org/virtualbox/%1/") 883 .arg (vbox.GetVersion().remove("_OSE")) + name; 884 QString target = QDir(vboxGlobal().virtualBox().GetHomeFolder()).absoluteFilePath(name); 885 886 // TODO: Think more about additions downloader... 887 //UIAdditionsDownloader *dl = 888 // new UIAdditionsDownloader(source, target, mDevicesInstallGuestToolsAction); 889 //machineWindowWrapper()->statusBar()->addWidget(dl, 0); 890 //dl->start(); 891 } 892 } 893 894 #ifdef VBOX_WITH_DEBUGGER_GUI 895 void UIMachineLogic::sltPrepareDebugMenu() 896 { 897 /* The "Logging" item. */ 898 bool fEnabled = false; 899 bool fChecked = false; 900 CConsole console = session().GetConsole(); 901 if (console.isOk()) 902 { 903 CMachineDebugger cdebugger = console.GetDebugger(); 904 if (console.isOk()) 905 { 906 fEnabled = true; 907 fChecked = cdebugger.GetLogEnabled() != FALSE; 908 } 909 } 910 if (fEnabled != actionsPool()->action(UIActionIndex_Toggle_Logging)->isEnabled()) 911 actionsPool()->action(UIActionIndex_Toggle_Logging)->setEnabled(fEnabled); 912 if (fChecked != actionsPool()->action(UIActionIndex_Toggle_Logging)->isChecked()) 913 actionsPool()->action(UIActionIndex_Toggle_Logging)->setChecked(fChecked); 914 } 915 916 void UIMachineLogic::sltShowDebugStatistics() 917 { 918 if (dbgCreated()) 919 m_dbgGuiVT->pfnShowStatistics(m_dbgGui); 920 } 921 922 void UIMachineLogic::sltShowDebugCommandLine() 923 { 924 if (dbgCreated()) 925 m_dbgGuiVT->pfnShowCommandLine(m_dbgGui); 926 } 927 928 void UIMachineLogic::sltLoggingToggled(bool bState) 929 { 930 NOREF(bState); 931 CConsole console = session().GetConsole(); 932 if (console.isOk()) 933 { 934 CMachineDebugger cdebugger = console.GetDebugger(); 935 if (console.isOk()) 936 cdebugger.SetLogEnabled(bState); 937 } 938 } 939 #endif 940 941 void UIMachineLogic::sltUpdateMachineState(KMachineState machineState) 942 { 943 bool bGuruMeditation = false; 944 945 if (machineWindowWrapper() && m_machineState != machineState) 946 { 947 switch (machineState) 2591 948 { 2592 949 case KMachineState_Stuck: 2593 950 { 2594 guruMeditation = true;951 bGuruMeditation = true; 2595 952 break; 2596 953 } 2597 954 case KMachineState_Paused: 2598 955 { 2599 if (! mVmPauseAction->isChecked())2600 mVmPauseAction->setChecked(true);956 if (!actionsPool()->action(UIActionIndex_Toggle_Pause)->isChecked()) 957 actionsPool()->action(UIActionIndex_Toggle_Pause)->setChecked(true); 2601 958 break; 2602 959 } 2603 960 case KMachineState_Running: 2604 case KMachineState_Teleporting: /** @todo Live Migration: Check out this. */961 case KMachineState_Teleporting: 2605 962 case KMachineState_LiveSnapshotting: 2606 963 { 2607 if ( ( mMachineState == KMachineState_Paused 2608 || mMachineState == KMachineState_TeleportingPausedVM) 2609 && mVmPauseAction->isChecked() 2610 ) 2611 mVmPauseAction->setChecked (false); 964 if ((m_machineState == KMachineState_Paused || 965 m_machineState == KMachineState_TeleportingPausedVM) 966 && actionsPool()->action(UIActionIndex_Toggle_Pause)->isChecked()) 967 actionsPool()->action(UIActionIndex_Toggle_Pause)->setChecked(false); 2612 968 break; 2613 969 } … … 2617 973 case KMachineState_TeleportingIn: 2618 974 { 2619 /* The keyboard handler may wish to do some release logging 2620 on startup.Tell it that the logger is now active. */2621 doXKeyboardLogging 975 /* The keyboard handler may wish to do some release logging on startup. 976 * Tell it that the logger is now active. */ 977 doXKeyboardLogging(QX11Info::display()); 2622 978 break; 2623 979 } … … 2627 983 } 2628 984 2629 bool isRunningOrPaused = aState == KMachineState_Running 2630 || aState == KMachineState_Teleporting 2631 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2632 || aState == KMachineState_Paused; 2633 2634 /* Enable/Disable actions that are not managed by updateAppearanceOf() */ 2635 2636 mRunningActions->setEnabled ( aState == KMachineState_Running 2637 || aState == KMachineState_Teleporting 2638 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2639 ); 2640 mRunningOrPausedActions->setEnabled (isRunningOrPaused); 2641 2642 mMachineState = aState; 2643 2644 updateAppearanceOf (Caption | 2645 HardDiskStuff | DVDStuff | FloppyStuff | 2646 NetworkStuff | USBStuff | VRDPStuff | 2647 PauseAction | DisableMouseIntegrAction); 2648 2649 if ( aState == KMachineState_PoweredOff 2650 || aState == KMachineState_Saved 2651 || aState == KMachineState_Teleported 2652 || aState == KMachineState_Aborted 2653 ) 2654 { 2655 /* VM has been powered off or saved or aborted, no matter 2656 * internally or externally -- we must *safely* close the console 2657 * window unless auto closure is disabled. */ 2658 if (!mNoAutoClose) 2659 tryClose(); 2660 } 2661 } 2662 2663 if (guruMeditation) 2664 { 2665 mConsole->setIgnoreGuestResize (true); 2666 2667 CConsole console = mConsole->console(); 2668 QString logFolder = console.GetMachine().GetLogFolder(); 985 bool bIsRunning = machineState == KMachineState_Running || 986 machineState == KMachineState_Teleporting || 987 machineState == KMachineState_LiveSnapshotting; 988 989 bool bIsRunningOrPaused = machineState == KMachineState_Running || 990 machineState == KMachineState_Teleporting || 991 machineState == KMachineState_LiveSnapshotting || 992 machineState == KMachineState_Paused; 993 994 m_pRunningActions->setEnabled(bIsRunning); 995 m_pRunningOrPausedActions->setEnabled(bIsRunningOrPaused); 996 997 m_machineState = machineState; 998 999 updateAppearanceOf(UIVisualElement_WindowCaption | 1000 UIVisualElement_HDStuff | UIVisualElement_CDStuff | UIVisualElement_FDStuff | 1001 UIVisualElement_NetworkStuff | UIVisualElement_USBStuff | UIVisualElement_VRDPStuff | 1002 UIVisualElement_PauseStuff | UIVisualElement_MouseIntegrationStuff); 1003 1004 if (machineState == KMachineState_PoweredOff || 1005 machineState == KMachineState_Saved || 1006 machineState == KMachineState_Teleported || 1007 machineState == KMachineState_Aborted) 1008 { 1009 /* VM has been powered off or saved or aborted, no matter internally or externally. 1010 * We must *safely* close the console window unless auto closure is disabled: */ 1011 if (!m_bIsPreventAutoClose) 1012 machineWindowWrapper()->sltTryClose(); 1013 } 1014 } 1015 1016 if (bGuruMeditation) 1017 { 1018 machineWindowWrapper()->machineView()->setIgnoreGuestResize(true); 1019 1020 CConsole console = session().GetConsole(); 1021 QString strLogFolder = console.GetMachine().GetLogFolder(); 2669 1022 2670 1023 /* Take the screenshot for debugging purposes and save it */ 2671 QString fname = logFolder + "/VBox.png";2672 2673 CDisplay d sp= console.GetDisplay();2674 QImage shot = QImage (dsp.GetWidth(), dsp.GetHeight(), QImage::Format_RGB32);2675 d sp.TakeScreenShot(shot.bits(), shot.width(), shot.height());2676 shot.save (QFile::encodeName (fname), "PNG");2677 2678 if (vboxProblem().remindAboutGuruMeditation (console, QDir::toNativeSeparators (logFolder)))1024 QString strFileName = strLogFolder + "/VBox.png"; 1025 1026 CDisplay display = console.GetDisplay(); 1027 QImage shot = QImage(display.GetWidth(), display.GetHeight(), QImage::Format_RGB32); 1028 display.TakeScreenShot(shot.bits(), shot.width(), shot.height()); 1029 shot.save(QFile::encodeName(strFileName), "PNG"); 1030 1031 if (vboxProblem().remindAboutGuruMeditation(console, QDir::toNativeSeparators(strLogFolder))) 2679 1032 { 2680 1033 qApp->processEvents(); 2681 1034 console.PowerDown(); 2682 1035 if (!console.isOk()) 2683 vboxProblem().cannotStopMachine 1036 vboxProblem().cannotStopMachine(console); 2684 1037 } 2685 1038 } 2686 1039 2687 1040 #ifdef Q_WS_MAC 2688 if (mConsole) 2689 mConsole->updateDockOverlay(); 2690 #endif 2691 } 2692 2693 void VBoxConsoleWnd::updateMouseState (int aState) 2694 { 2695 mVmDisableMouseIntegrAction->setEnabled (aState & VBoxConsoleView::MouseAbsolute); 2696 2697 if ((aState & VBoxConsoleView::MouseAbsoluteDisabled) && 2698 (aState & VBoxConsoleView::MouseAbsolute) && 2699 !(aState & VBoxConsoleView::MouseCaptured)) 2700 { 2701 mMouseLed->setState (4); 2702 } 2703 else 2704 { 2705 mMouseLed->setState (aState & (VBoxConsoleView::MouseAbsolute | VBoxConsoleView::MouseCaptured)); 2706 } 2707 } 2708 2709 void VBoxConsoleWnd::updateAdditionsState (const QString &aVersion, 2710 bool aActive, 2711 bool aSeamlessSupported, 2712 bool aGraphicsSupported) 2713 { 2714 mVmAutoresizeGuestAction->setEnabled (aActive && aGraphicsSupported); 2715 if ((mIsSeamlessSupported != aSeamlessSupported) || 2716 (mIsGraphicsSupported != aGraphicsSupported)) 2717 { 2718 mVmSeamlessAction->setEnabled (aSeamlessSupported && aGraphicsSupported); 2719 mIsSeamlessSupported = aSeamlessSupported; 2720 mIsGraphicsSupported = aGraphicsSupported; 2721 /* If seamless mode should be enabled then check if it is enabled 2722 * currently and re-enable it if open-view procedure is finished */ 2723 if (mVmSeamlessAction->isChecked() && mIsOpenViewFinished && aSeamlessSupported && aGraphicsSupported) 2724 toggleFullscreenMode (true, true); 2725 /* Disable auto-resizing if advanced graphics are not available */ 2726 mConsole->setAutoresizeGuest (mIsGraphicsSupported && mVmAutoresizeGuestAction->isChecked()); 2727 mVmAutoresizeGuestAction->setEnabled (mIsGraphicsSupported); 1041 if (machineWindowWrapper()) 1042 machineWindowWrapper()->updateDockOverlay(); 1043 #endif 1044 } 1045 1046 void UIMachineLogic::sltUpdateAdditionsState(const QString &strVersion, bool bIsActive, 1047 bool bIsSeamlessSupported, bool bIsGraphicsSupported) 1048 { 1049 actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->setEnabled(bIsActive && bIsGraphicsSupported); 1050 actionsPool()->action(UIActionIndex_Toggle_Seamless)->setEnabled(bIsActive && bIsGraphicsSupported && bIsSeamlessSupported); 1051 1052 if ((m_bIsSeamlessSupported != bIsSeamlessSupported) || (m_bIsGraphicsSupported != bIsGraphicsSupported)) 1053 { 1054 m_bIsSeamlessSupported = bIsSeamlessSupported; 1055 m_bIsGraphicsSupported = bIsGraphicsSupported; 1056 1057 // TODO: How should that be performed now? 1058 /* If seamless mode should be enabled then check if it is enabled currently and re-enable it if open-view procedure is finished */ 1059 //if (actionsPool()->action(UIActionIndex_Toggle_Seamless)->isChecked() && m_bIsOpenViewFinished && bIsGraphicsSupported && bIsSeamlessSupported) 1060 // toggleFullscreenMode(true, true); 2728 1061 } 2729 1062 2730 1063 /* Check the GA version only in case of additions are active */ 2731 if (! aActive)1064 if (!bIsActive) 2732 1065 return; 2733 1066 2734 1067 /* Check the Guest Additions version and warn the user about possible 2735 1068 * compatibility issues in case if the installed version is outdated. */ 2736 uint version = aVersion.toUInt(); 2737 QString versionStr = QString ("%1.%2") 2738 .arg (RT_HIWORD (version)).arg (RT_LOWORD (version)); 2739 QString expectedStr = QString ("%1.%2") 2740 .arg (VMMDEV_VERSION_MAJOR).arg (VMMDEV_VERSION_MINOR); /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 2741 2742 if (RT_HIWORD (version) < VMMDEV_VERSION_MAJOR) 2743 { 2744 vboxProblem().warnAboutTooOldAdditions (this, versionStr, expectedStr); 2745 } 2746 else if (RT_HIWORD (version) == VMMDEV_VERSION_MAJOR && 2747 RT_LOWORD (version) < VMMDEV_VERSION_MINOR) 2748 { 2749 vboxProblem().warnAboutOldAdditions (this, versionStr, expectedStr); 2750 } 2751 else if (version > VMMDEV_VERSION) 2752 { 2753 vboxProblem().warnAboutNewAdditions (this, versionStr, expectedStr); 2754 } 2755 } 2756 2757 void VBoxConsoleWnd::updateNetworkAdaptersState() 2758 { 2759 updateAppearanceOf (NetworkStuff); 2760 } 2761 2762 void VBoxConsoleWnd::updateUsbState() 2763 { 2764 updateAppearanceOf (USBStuff); 2765 } 2766 2767 void VBoxConsoleWnd::updateMediaDriveState (VBoxDefs::MediumType aType) 2768 { 2769 Assert (aType == VBoxDefs::MediumType_DVD || aType == VBoxDefs::MediumType_Floppy); 2770 updateAppearanceOf (aType == VBoxDefs::MediumType_DVD ? DVDStuff : 2771 aType == VBoxDefs::MediumType_Floppy ? FloppyStuff : 2772 AllStuff); 2773 } 2774 2775 void VBoxConsoleWnd::updateSharedFoldersState() 2776 { 2777 updateAppearanceOf (SharedFolderStuff); 2778 } 2779 2780 /** 2781 * This slot is called just after leaving the fullscreen/seamless mode, 2782 * when the console was resized to previous size. 2783 */ 2784 void VBoxConsoleWnd::onExitFullscreen() 2785 { 2786 mConsole->setIgnoreMainwndResize (false); 2787 } 2788 2789 void VBoxConsoleWnd::unlockActionsSwitch() 2790 { 2791 if (mIsSeamless) 2792 mVmSeamlessAction->setEnabled (true); 2793 else if (mIsFullscreen) 2794 mVmFullscreenAction->setEnabled (true); 2795 else 2796 { 2797 mVmSeamlessAction->setEnabled (mIsSeamlessSupported && mIsGraphicsSupported); 2798 mVmFullscreenAction->setEnabled (true); 2799 } 2800 2801 #ifdef Q_WS_MAC 2802 if (!mIsSeamless) 2803 { 2804 /* Fade back to the normal gamma */ 2805 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 2806 CGReleaseDisplayFadeReservation (mFadeToken); 2807 } 2808 mConsole->setMouseCoalescingEnabled (true); 2809 #endif 2810 1069 uint uVersion = strVersion.toUInt(); 1070 /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 1071 QString strRealVersion = QString("%1.%2").arg(RT_HIWORD(uVersion)).arg(RT_LOWORD(uVersion)); 1072 QString strExpectedVersion = QString("%1.%2").arg(VMMDEV_VERSION_MAJOR).arg(VMMDEV_VERSION_MINOR); 1073 1074 if (RT_HIWORD(uVersion) < VMMDEV_VERSION_MAJOR) 1075 { 1076 vboxProblem().warnAboutTooOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion); 1077 } 1078 else if (RT_HIWORD(uVersion) == VMMDEV_VERSION_MAJOR && RT_LOWORD(uVersion) < VMMDEV_VERSION_MINOR) 1079 { 1080 vboxProblem().warnAboutOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion); 1081 } 1082 else if (uVersion > VMMDEV_VERSION) 1083 { 1084 vboxProblem().warnAboutNewAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion); 1085 } 1086 } 1087 1088 void UIMachineLogic::sltUpdateMouseState(int iState) 1089 { 1090 actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setEnabled(iState & UIMouseStateType_MouseAbsolute); 1091 } 1092 1093 void UIMachineLogic::prepareActionGroups() 1094 { 1095 /* Create group for all actions that are enabled only when the VM is running. 1096 * Note that only actions whose enabled state depends exclusively on the 1097 * execution state of the VM are added to this group. */ 1098 m_pRunningActions = new QActionGroup(this); 1099 m_pRunningActions->setExclusive(false); 1100 1101 /* Create group for all actions that are enabled when the VM is running or paused. 1102 * Note that only actions whose enabled state depends exclusively on the 1103 * execution state of the VM are added to this group. */ 1104 m_pRunningOrPausedActions = new QActionGroup(this); 1105 m_pRunningOrPausedActions->setExclusive(false); 1106 1107 // TODO: Move actions into approprivate action groups! 1108 } 1109 1110 void UIMachineLogic::prepareActionConnections() 1111 { 1112 /* "Machine" actions connections */ 1113 connect(actionsPool()->action(UIActionIndex_Simple_AdjustWindow), SIGNAL(triggered()), 1114 this, SLOT(sltAdjustWindow())); 1115 connect(actionsPool()->action(UIActionIndex_Toggle_MouseIntegration), SIGNAL(toggled(bool)), 1116 this, SLOT(sltToggleMouseIntegration(bool))); 1117 connect(actionsPool()->action(UIActionIndex_Simple_TypeCAD), SIGNAL(triggered()), 1118 this, SLOT(sltTypeCAD())); 2811 1119 #ifdef Q_WS_X11 2812 if (vboxGlobal().isKWinManaged() && !mIsSeamless && !mIsFullscreen) 2813 { 2814 /* Workaround for a KWin bug to let console window to exit 2815 * seamless mode correctly. */ 2816 setWindowFlags(Qt::Window); 2817 setVisible(true); 2818 } 2819 #endif 2820 } 2821 2822 void VBoxConsoleWnd::mtExitMode() 2823 { 2824 if (mIsSeamless) 2825 mVmSeamlessAction->toggle(); 2826 else 2827 mVmFullscreenAction->toggle(); 2828 } 2829 2830 void VBoxConsoleWnd::mtCloseVM() 2831 { 2832 mVmCloseAction->trigger(); 2833 } 2834 2835 void VBoxConsoleWnd::mtMaskUpdate() 2836 { 2837 if (mIsSeamless) 2838 setMask (mConsole->lastVisibleRegion()); 2839 } 2840 2841 void VBoxConsoleWnd::changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent) 2842 { 2843 #ifdef Q_WS_MAC 2844 if (mConsole) 2845 { 2846 mConsole->setDockIconEnabled (aEvent.mChanged); 2847 mConsole->updateDockOverlay(); 2848 } 2849 #else 2850 Q_UNUSED (aEvent); 2851 #endif 2852 } 2853 2854 void VBoxConsoleWnd::changePresentationMode (const VBoxChangePresentationModeEvent &aEvent) 2855 { 2856 Q_UNUSED (aEvent); 2857 #ifdef Q_WS_MAC 2858 # ifdef QT_MAC_USE_COCOA 2859 if (mIsFullscreen) 2860 { 2861 /* First check if we are on the primary screen, only than the 2862 presentation mode have to be changed. */ 2863 QDesktopWidget* pDesktop = QApplication::desktop(); 2864 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 2865 { 2866 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_PresentationModeEnabled).toLower(); 2867 /* Default to false if it is an empty value */ 2868 if (testStr.isEmpty() || testStr == "false") 2869 SetSystemUIMode (kUIModeAllHidden, 0); 2870 else 2871 SetSystemUIMode (kUIModeAllSuppressed, 0); 2872 } 2873 } 2874 else 2875 SetSystemUIMode (kUIModeNormal, 0); 2876 # endif /* QT_MAC_USE_COCOA */ 2877 #endif 2878 } 2879 2880 /** 2881 * Called (on non-UI thread!) when a global GUI setting changes. 2882 */ 2883 void VBoxConsoleWnd::processGlobalSettingChange (const char * /* aPublicName */, const char * /* aName */) 2884 { 2885 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 2886 } 2887 2888 /** 2889 * This function checks the status of required features and 2890 * makes a warning and/or some action if something necessary 2891 * is not in good condition. 2892 * Does nothing if no console view was opened. 2893 */ 2894 void VBoxConsoleWnd::checkRequiredFeatures() 2895 { 2896 if (!mConsole) return; 2897 2898 CConsole console = mConsole->console(); 1120 connect(actionsPool()->action(UIActionIndex_Simple_TypeCABS), SIGNAL(triggered()), 1121 this, SLOT(sltTypeCABS())); 1122 #endif 1123 connect(actionsPool()->action(UIActionIndex_Simple_TakeSnapshot), SIGNAL(triggered()), 1124 this, SLOT(sltTakeSnapshot())); 1125 connect(actionsPool()->action(UIActionIndex_Simple_InformationDialog), SIGNAL(triggered()), 1126 this, SLOT(sltShowInformationDialog())); 1127 connect(actionsPool()->action(UIActionIndex_Simple_Reset), SIGNAL(triggered()), 1128 this, SLOT(sltReset())); 1129 connect(actionsPool()->action(UIActionIndex_Toggle_Pause), SIGNAL(toggled(bool)), 1130 this, SLOT(sltPause(bool))); 1131 connect(actionsPool()->action(UIActionIndex_Simple_Shutdown), SIGNAL(triggered()), 1132 this, SLOT(sltACPIShutdown())); 1133 connect(actionsPool()->action(UIActionIndex_Simple_Close), SIGNAL(triggered()), 1134 this, SLOT(sltClose())); 1135 1136 /* "Devices" actions connections */ 1137 connect(actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu(), SIGNAL(aboutToShow()), 1138 this, SLOT(sltPrepareStorageMenu())); 1139 connect(actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu(), SIGNAL(aboutToShow()), 1140 this, SLOT(sltPrepareStorageMenu())); 1141 connect(actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog), SIGNAL(triggered()), 1142 this, SLOT(sltOpenNetworkAdaptersDialog())); 1143 connect(actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog), SIGNAL(triggered()), 1144 this, SLOT(sltOpenSharedFoldersDialog())); 1145 connect(actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu(), SIGNAL(aboutToShow()), 1146 this, SLOT(sltPrepareUSBMenu())); 1147 connect(actionsPool()->action(UIActionIndex_Toggle_VRDP), SIGNAL(toggled(bool)), 1148 this, SLOT(sltSwitchVrdp(bool))); 1149 connect(actionsPool()->action(UIActionIndex_Simple_InstallGuestTools), SIGNAL(triggered()), 1150 this, SLOT(sltInstallGuestAdditions())); 1151 1152 #ifdef VBOX_WITH_DEBUGGER_GUI 1153 /* "Debug" actions connections */ 1154 connect(actionsPool()->action(UIActionIndex_Menu_Debug)->menu(), SIGNAL(aboutToShow()), 1155 this, SLOT(sltPrepareDebugMenu())); 1156 connect(actionsPool()->action(UIActionIndex_Simple_Statistics), SIGNAL(triggered()), 1157 this, SLOT(sltShowDebugStatistics())); 1158 connect(actionsPool()->action(UIActionIndex_Simple_CommandLine), SIGNAL(triggered()), 1159 this, SLOT(sltShowDebugCommandLine())); 1160 connect(actionsPool()->action(UIActionIndex_Toggle_Logging), SIGNAL(toggled(bool)), 1161 this, SLOT(dbgLoggingToggled(bool))); 1162 #endif 1163 } 1164 1165 void UIMachineLogic::prepareRequiredFeatures() 1166 { 1167 CConsole console = session().GetConsole(); 2899 1168 2900 1169 /* Check if the virtualization feature is required. */ 2901 bool is64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType ( 2902 console.GetGuest().GetOSTypeId()).GetIs64Bit(); 2903 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType ( 2904 console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 2905 Assert(!is64BitsGuest || fRecommendVirtEx); 2906 bool isVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 2907 if (fRecommendVirtEx && !isVirtEnabled) 1170 bool bIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetIs64Bit(); 1171 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 1172 AssertMsg(!bIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n")); 1173 bool bIsVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 1174 if (fRecommendVirtEx && !bIsVirtEnabled) 2908 1175 { 2909 1176 bool ret; 2910 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost() 2911 .GetProcessorFeature (KProcessorFeature_HWVirtEx); 2912 2913 vmPause (true); 2914 2915 if (is64BitsGuest) 1177 1178 // TODO: Check that logic! 1179 //sltPause(true); 1180 1181 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx); 1182 1183 if (bIs64BitsGuest) 2916 1184 ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported); 2917 1185 else 2918 1186 ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported); 2919 1187 2920 if (ret == true) 2921 close(); 1188 // TODO: Close application! 1189 //if (ret == true) 1190 // machineWindowWrapper()->machineWindow()->close(); 1191 // TODO: Check that logic! 1192 //else 1193 // sltPause(false); 1194 } 1195 1196 #ifdef Q_WS_MAC 1197 # ifdef VBOX_WITH_ICHAT_THEATER 1198 initSharedAVManager(); 1199 # endif 1200 #endif 1201 } 1202 1203 void UIMachineLogic::loadLogicSettings() 1204 { 1205 CMachine machine = session().GetMachine(); 1206 1207 /* Extra-data settings */ 1208 { 1209 QString strSettings; 1210 1211 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest); 1212 if (strSettings != "off") 1213 actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->setChecked(true); 1214 1215 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun); 1216 if (strSettings == "yes") 1217 m_bIsFirstTimeStarted = true; 1218 1219 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime); 1220 if (strSettings == "no") 1221 m_bIsAutoSaveMedia = false; 1222 } 1223 1224 /* Initial settings */ 1225 { 1226 /* Initialize storage stuff: */ 1227 int iDevicesCountCD = 0; 1228 int iDevicesCountFD = 0; 1229 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 1230 foreach (const CMediumAttachment &attachment, attachments) 1231 { 1232 if (attachment.GetType() == KDeviceType_DVD) 1233 ++ iDevicesCountCD; 1234 if (attachment.GetType() == KDeviceType_Floppy) 1235 ++ iDevicesCountFD; 1236 } 1237 actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->setData(iDevicesCountCD); 1238 actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->setData(iDevicesCountFD); 1239 actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->setVisible(iDevicesCountCD); 1240 actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->setVisible(iDevicesCountFD); 1241 } 1242 1243 /* Availability settings */ 1244 { 1245 /* USB Stuff: */ 1246 CUSBController usbController = machine.GetUSBController(); 1247 if (usbController.isNull()) 1248 { 1249 /* Hide USB_Menu: */ 1250 actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setVisible(false); 1251 } 2922 1252 else 2923 vmPause (false); 2924 } 2925 } 2926 2927 void VBoxConsoleWnd::activateUICustomizations() 2928 { 2929 VBoxGlobalSettings settings = vboxGlobal().settings(); 2930 /* Process known keys */ 2931 menuBar()->setHidden (settings.isFeatureActive ("noMenuBar")); 2932 statusBar()->setHidden (settings.isFeatureActive ("noStatusBar")); 2933 } 2934 2935 void VBoxConsoleWnd::updateAppearanceOf (int aElement) 2936 { 2937 if (!mConsole) return; 2938 2939 CMachine machine = mSession.GetMachine(); 2940 CConsole console = mConsole->console(); 2941 2942 bool isStrictRunningOrPaused = mMachineState == KMachineState_Running 2943 || mMachineState == KMachineState_Paused; 2944 bool isRunningOrPaused = isStrictRunningOrPaused 2945 || mMachineState == KMachineState_Teleporting 2946 || mMachineState == KMachineState_LiveSnapshotting; 2947 2948 if (aElement & Caption) 2949 { 2950 QString snapshotName; 2951 if (machine.GetSnapshotCount() > 0) 2952 { 2953 CSnapshot snapshot = machine.GetCurrentSnapshot(); 2954 snapshotName = " (" + snapshot.GetName() + ")"; 2955 } 2956 setWindowTitle (machine.GetName() + snapshotName + 2957 " [" + vboxGlobal().toString (mMachineState) + "] - " + 2958 mCaptionPrefix); 2959 mMiniToolBar->setDisplayText (machine.GetName() + snapshotName); 2960 } 2961 if (aElement & HardDiskStuff) 2962 { 2963 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2964 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 2965 QString data; 2966 bool attachmentsPresent = false; 2967 1253 { 1254 /* Enable/Disable USB_Menu: */ 1255 actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(usbController.GetEnabled()); 1256 } 1257 1258 /* VRDP Stuff: */ 1259 CVRDPServer vrdpServer = machine.GetVRDPServer(); 1260 if (vrdpServer.isNull()) 1261 { 1262 /* Hide VRDP Action: */ 1263 actionsPool()->action(UIActionIndex_Toggle_VRDP)->setVisible(false); 1264 } 1265 } 1266 } 1267 1268 void UIMachineLogic::saveLogicSettings() 1269 { 1270 CMachine machine = session().GetMachine(); 1271 1272 /* Extra-data settings */ 1273 { 1274 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest, 1275 actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ? "on" : "off"); 1276 1277 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString()); 1278 1279 // TODO: Move to fullscreen/seamless logic: 1280 //machine.SetExtraData(VBoxDefs::GUI_MiniToolBarAutoHide, mMiniToolBar->isAutoHide() ? "on" : "off"); 1281 } 1282 } 1283 1284 bool UIMachineLogic::pause(bool bOn) 1285 { 1286 if (isPaused() == bOn) 1287 return true; 1288 1289 CConsole console = session().GetConsole(); 1290 1291 if (bOn) 1292 console.Pause(); 1293 else 1294 console.Resume(); 1295 1296 bool ok = console.isOk(); 1297 if (!ok) 1298 { 1299 if (bOn) 1300 vboxProblem().cannotPauseMachine(console); 1301 else 1302 vboxProblem().cannotResumeMachine(console); 1303 } 1304 1305 return ok; 1306 } 1307 1308 void UIMachineLogic::installGuestAdditionsFrom(const QString &strSource) 1309 { 1310 CMachine machine = session().GetMachine(); 1311 CVirtualBox vbox = vboxGlobal().virtualBox(); 1312 QString strUuid; 1313 1314 CMedium image = vbox.FindDVDImage(strSource); 1315 if (image.isNull()) 1316 { 1317 image = vbox.OpenDVDImage(strSource, strUuid); 1318 if (vbox.isOk()) 1319 strUuid = image.GetId(); 1320 } 1321 else 1322 strUuid = image.GetId(); 1323 1324 if (!vbox.isOk()) 1325 { 1326 vboxProblem().cannotOpenMedium(machineWindowWrapper()->machineWindow(), vbox, VBoxDefs::MediumType_DVD, strSource); 1327 return; 1328 } 1329 1330 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n")); 1331 1332 QString strCntName; 1333 LONG iCntPort = -1, iCntDevice = -1; 1334 /* Searching for the first suitable slot */ 1335 { 2968 1336 CStorageControllerVector controllers = machine.GetStorageControllers(); 2969 foreach (const CStorageController &controller, controllers) 2970 { 2971 QString attData; 2972 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 2973 foreach (const CMediumAttachment &attachment, attachments) 1337 int i = 0; 1338 while (i < controllers.size() && strCntName.isNull()) 1339 { 1340 CStorageController controller = controllers[i]; 1341 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName()); 1342 int j = 0; 1343 while (j < attachments.size() && strCntName.isNull()) 2974 1344 { 2975 if (attachment.GetType() != KDeviceType_HardDisk) 2976 continue; 2977 attData += QString ("<br> <nobr>%1: %2</nobr>") 2978 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 2979 .arg (VBoxMedium (attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 2980 attachmentsPresent = true; 1345 CMediumAttachment attachment = attachments[j]; 1346 if (attachment.GetType() == KDeviceType_DVD) 1347 { 1348 strCntName = controller.GetName(); 1349 iCntPort = attachment.GetPort(); 1350 iCntDevice = attachment.GetDevice(); 1351 } 1352 ++ j; 2981 1353 } 2982 if (!attData.isNull()) 2983 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 2984 } 2985 2986 if (!attachmentsPresent) 2987 data += tr ("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 2988 2989 mHDLed->setToolTip (tip.arg (data)); 2990 mHDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 2991 } 2992 if (aElement & DVDStuff) 2993 { 2994 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2995 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 2996 QString data; 2997 bool attachmentsPresent = false; 2998 2999 CStorageControllerVector controllers = machine.GetStorageControllers(); 3000 foreach (const CStorageController &controller, controllers) 3001 { 3002 QString attData; 3003 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3004 foreach (const CMediumAttachment &attachment, attachments) 1354 ++ i; 1355 } 1356 } 1357 1358 if (!strCntName.isNull()) 1359 { 1360 bool isMounted = false; 1361 1362 /* Mount medium to the predefined port/device */ 1363 machine.MountMedium(strCntName, iCntPort, iCntDevice, strUuid, false /* force */); 1364 if (machine.isOk()) 1365 isMounted = true; 1366 else 1367 { 1368 /* Ask for force mounting */ 1369 if (vboxProblem().cannotRemountMedium(machineWindowWrapper()->machineWindow(), machine, VBoxMedium(image, VBoxDefs::MediumType_DVD), 1370 true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 3005 1371 { 3006 if (attachment.GetType() != KDeviceType_DVD) 3007 continue; 3008 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_DVD); 3009 attData += QString ("<br> <nobr>%1: %2</nobr>") 3010 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3011 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3012 if (!vboxMedium.isNull()) 3013 attachmentsPresent = true; 1372 /* Force mount medium to the predefined port/device */ 1373 machine.MountMedium(strCntName, iCntPort, iCntDevice, strUuid, true /* force */); 1374 if (machine.isOk()) 1375 isMounted = true; 1376 else 1377 vboxProblem().cannotRemountMedium(machineWindowWrapper()->machineWindow(), machine, VBoxMedium(image, VBoxDefs::MediumType_DVD), 1378 true /* mount? */, false /* retry? */); 3014 1379 } 3015 if (!attData.isNull()) 3016 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3017 } 3018 3019 if (data.isNull()) 3020 data = tr ("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 3021 3022 mCDLed->setToolTip (tip.arg (data)); 3023 mCDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3024 } 3025 #if 0 /* TODO: Allow to setup status-bar! */ 3026 if (aElement & FloppyStuff) 3027 { 3028 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 3029 "of the floppy devices:</nobr>%1</p>", "FD tooltip"); 3030 QString data; 3031 bool attachmentsPresent = false; 3032 3033 CStorageControllerVector controllers = machine.GetStorageControllers(); 3034 foreach (const CStorageController &controller, controllers) 3035 { 3036 QString attData; 3037 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3038 foreach (const CMediumAttachment &attachment, attachments) 1380 } 1381 1382 /* Save medium mounted at runtime */ 1383 if (isMounted && m_bIsAutoSaveMedia) 1384 { 1385 machine.SaveSettings(); 1386 if (!machine.isOk()) 1387 vboxProblem().cannotSaveMachineSettings(machine); 1388 } 1389 } 1390 else 1391 vboxProblem().cannotMountGuestAdditions(machine.GetName()); 1392 } 1393 1394 int UIMachineLogic::searchMaxSnapshotIndex(const CMachine &machine, 1395 const CSnapshot &snapshot, 1396 const QString &strNameTemplate) 1397 { 1398 int iMaxIndex = 0; 1399 QRegExp regExp(QString("^") + strNameTemplate.arg("([0-9]+)") + QString("$")); 1400 if (!snapshot.isNull()) 1401 { 1402 /* Check the current snapshot name */ 1403 QString strName = snapshot.GetName(); 1404 int iPos = regExp.indexIn(strName); 1405 if (iPos != -1) 1406 iMaxIndex = regExp.cap(1).toInt() > iMaxIndex ? regExp.cap(1).toInt() : iMaxIndex; 1407 /* Traversing all the snapshot children */ 1408 foreach (const CSnapshot &child, snapshot.GetChildren()) 1409 { 1410 int iMaxIndexOfChildren = searchMaxSnapshotIndex(machine, child, strNameTemplate); 1411 iMaxIndex = iMaxIndexOfChildren > iMaxIndex ? iMaxIndexOfChildren : iMaxIndex; 1412 } 1413 } 1414 return iMaxIndex; 1415 } 1416 1417 #ifdef VBOX_WITH_DEBUGGER_GUI 1418 bool UIMachineLogic::dbgCreated() 1419 { 1420 if (m_dbgGui) 1421 return true; 1422 1423 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 1424 if (hLdrMod == NIL_RTLDRMOD) 1425 return false; 1426 1427 PFNDBGGUICREATE pfnGuiCreate; 1428 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 1429 if (RT_SUCCESS (rc)) 1430 { 1431 ISession *pISession = session().raw(); 1432 rc = pfnGuiCreate (pISession, &m_dbgGui, &m_dbgGuiVT); 1433 if (RT_SUCCESS (rc)) 1434 { 1435 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (m_dbgGuiVT->u32Version, DBGGUIVT_VERSION) || 1436 m_dbgGuiVT->u32EndVersion == m_dbgGuiVT->u32Version) 3039 1437 { 3040 if (attachment.GetType() != KDeviceType_Floppy) 3041 continue; 3042 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_Floppy); 3043 attData += QString ("<br> <nobr>%1: %2</nobr>") 3044 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3045 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3046 if (!vboxMedium.isNull()) 3047 attachmentsPresent = true; 1438 m_dbgGuiVT->pfnSetParent (m_dbgGui, (QWidget*) machineWindowWrapper()); 1439 m_dbgGuiVT->pfnSetMenu (m_dbgGui, (QMenu*) actionsPool()->action(UIActionIndex_Menu_Debug)); 1440 dbgAdjustRelativePos(); 1441 return true; 3048 1442 } 3049 if (!attData.isNull()) 3050 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3051 } 3052 3053 if (data.isNull()) 3054 data = tr ("<br><nobr><b>No floppy devices attached</b></nobr>", "FD tooltip"); 3055 3056 mFDLed->setToolTip (tip.arg (data)); 3057 mFDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3058 } 3059 #endif 3060 if (aElement & NetworkStuff) 3061 { 3062 ulong maxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 3063 ulong count = 0; 3064 for (ulong slot = 0; slot < maxCount; ++ slot) 3065 if (machine.GetNetworkAdapter (slot).GetEnabled()) 3066 ++ count; 3067 mNetLed->setState (count > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 3068 3069 mDevicesNetworkDialogAction->setEnabled (isStrictRunningOrPaused && count > 0); 3070 mDevicesNetworkMenu->setEnabled (isStrictRunningOrPaused && count > 0); 3071 3072 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of the " 3073 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 3074 QString info; 3075 3076 for (ulong slot = 0; slot < maxCount; ++ slot) 3077 { 3078 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot); 3079 if (adapter.GetEnabled()) 3080 info += tr ("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 3081 .arg (slot + 1) 3082 .arg (vboxGlobal().toString (adapter.GetAttachmentType())) 3083 .arg (adapter.GetCableConnected() ? 3084 tr ("connected", "Network adapters tooltip") : 3085 tr ("disconnected", "Network adapters tooltip")); 3086 } 3087 3088 if (info.isNull()) 3089 info = tr ("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 3090 3091 mNetLed->setToolTip (tip.arg (info)); 3092 } 3093 if (aElement & USBStuff) 3094 { 3095 if (!mUSBLed->isHidden()) 3096 { 3097 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3098 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 3099 QString info; 3100 3101 CUSBController usbctl = machine.GetUSBController(); 3102 if (!usbctl.isNull() && usbctl.GetEnabled()) 3103 { 3104 mDevicesUSBMenu->setEnabled (isStrictRunningOrPaused); 3105 3106 CUSBDeviceVector devsvec = console.GetUSBDevices(); 3107 for (int i = 0; i < devsvec.size(); ++ i) 3108 { 3109 CUSBDevice usb = devsvec [i]; 3110 info += QString ("<br><b><nobr>%1</nobr></b>").arg (vboxGlobal().details (usb)); 3111 } 3112 if (info.isNull()) 3113 info = tr ("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 3114 } 3115 else 3116 { 3117 mDevicesUSBMenu->setEnabled (false); 3118 info = tr ("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 3119 } 3120 3121 mUSBLed->setToolTip (tip.arg (info)); 3122 } 3123 } 3124 if (aElement & VRDPStuff) 3125 { 3126 CVRDPServer vrdpsrv = mSession.GetMachine().GetVRDPServer(); 3127 if (!vrdpsrv.isNull()) 3128 { 3129 /* update menu&status icon state */ 3130 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 3131 mDevicesSwitchVrdpAction->setChecked (isVRDPEnabled); 3132 #if 0 /* TODO: Allow to setup status-bar! */ 3133 mVrdpLed->setState (isVRDPEnabled ? 1 : 0); 3134 3135 QString tip = tr ("Indicates whether the Remote Display (VRDP Server) " 3136 "is enabled (<img src=:/vrdp_16px.png/>) or not " 3137 "(<img src=:/vrdp_disabled_16px.png/>)."); 3138 if (vrdpsrv.GetEnabled()) 3139 tip += tr ("<hr>The VRDP Server is listening on port %1").arg (vrdpsrv.GetPort()); 3140 mVrdpLed->setToolTip (tip); 3141 #endif 3142 } 3143 } 3144 if (aElement & SharedFolderStuff) 3145 { 3146 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3147 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 3148 3149 QString data; 3150 QMap <QString, QString> sfs; 3151 3152 mDevicesSFMenu->setEnabled (true); 3153 3154 /* Permanent folders */ 3155 CSharedFolderVector psfvec = machine.GetSharedFolders(); 3156 3157 for (int i = 0; i < psfvec.size(); ++ i) 3158 { 3159 CSharedFolder sf = psfvec [i]; 3160 sfs.insert (sf.GetName(), sf.GetHostPath()); 3161 } 3162 3163 /* Transient folders */ 3164 CSharedFolderVector tsfvec = console.GetSharedFolders(); 3165 3166 for (int i = 0; i < tsfvec.size(); ++ i) 3167 { 3168 CSharedFolder sf = tsfvec[i]; 3169 sfs.insert (sf.GetName(), sf.GetHostPath()); 3170 } 3171 3172 for (QMap <QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 3173 { 3174 /* Select slashes depending on the OS type */ 3175 if (VBoxGlobal::isDOSType (console.GetGuest().GetOSTypeId())) 3176 data += QString ("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 3177 .arg (it.key(), it.value()); 3178 else 3179 data += QString ("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 3180 .arg (it.key(), it.value()); 3181 } 3182 3183 if (sfs.count() == 0) 3184 data = tr ("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 3185 3186 mSFLed->setToolTip (tip.arg (data)); 3187 } 3188 if (aElement & VirtualizationStuff) 3189 { 3190 bool virtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 3191 QString virtualization = virtEnabled ? 3192 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") : 3193 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)"); 3194 3195 bool nestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 3196 QString nestedPaging = nestEnabled ? 3197 VBoxVMInformationDlg::tr ("Enabled", "nested paging") : 3198 VBoxVMInformationDlg::tr ("Disabled", "nested paging"); 3199 3200 QString tip (tr ("Indicates the status of the hardware virtualization " 3201 "features used by this virtual machine:" 3202 "<br><nobr><b>%1:</b> %2</nobr>" 3203 "<br><nobr><b>%3:</b> %4</nobr>", 3204 "Virtualization Stuff LED") 3205 .arg (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization) 3206 .arg (VBoxVMInformationDlg::tr ("Nested Paging"), nestedPaging)); 3207 3208 int cpuCount = console.GetMachine().GetCPUCount(); 3209 if (cpuCount > 1) 3210 tip += tr ("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 3211 .arg (VBoxGlobal::tr ("Processor(s)", "details report")).arg (cpuCount); 3212 3213 mVirtLed->setToolTip (tip); 3214 mVirtLed->setState (virtEnabled); 3215 } 3216 if (aElement & PauseAction) 3217 { 3218 if (!mVmPauseAction->isChecked()) 3219 { 3220 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Pause"), "P")); 3221 mVmPauseAction->setStatusTip (tr ("Suspend the execution of the virtual machine")); 1443 1444 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 1445 m_dbgGuiVT->u32Version, m_dbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3222 1446 } 3223 1447 else 3224 { 3225 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("R&esume"), "P")); 3226 mVmPauseAction->setStatusTip (tr ("Resume the execution of the virtual machine" ) ); 3227 } 3228 mVmPauseAction->setEnabled (isRunningOrPaused); 3229 } 3230 if (aElement & DisableMouseIntegrAction) 3231 { 3232 if (!mVmDisableMouseIntegrAction->isChecked()) 3233 { 3234 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Disable &Mouse Integration"), "I")); 3235 mVmDisableMouseIntegrAction->setStatusTip (tr ("Temporarily disable host mouse pointer integration")); 3236 } 3237 else 3238 { 3239 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Enable &Mouse Integration"), "I")); 3240 mVmDisableMouseIntegrAction->setStatusTip (tr ("Enable temporarily disabled host mouse pointer integration")); 3241 } 3242 if ( mMachineState == KMachineState_Running 3243 || mMachineState == KMachineState_Teleporting 3244 || mMachineState == KMachineState_LiveSnapshotting 3245 ) 3246 mVmDisableMouseIntegrAction->setEnabled (mConsole->isMouseAbsolute()); 3247 else 3248 mVmDisableMouseIntegrAction->setEnabled (false); 3249 } 3250 } 3251 3252 /** 3253 * @return @c true if successfully performed the requested operation and false 3254 * otherwise. 3255 */ 3256 bool VBoxConsoleWnd::toggleFullscreenMode (bool aOn, bool aSeamless) 1448 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 1449 } 1450 else 1451 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 1452 1453 m_dbgGui = 0; 1454 m_dbgGuiVT = 0; 1455 return false; 1456 } 1457 1458 void UIMachineLogic::dbgDestroy() 1459 { 1460 if (m_dbgGui) 1461 { 1462 m_dbgGuiVT->pfnDestroy(m_dbgGui); 1463 m_dbgGui = 0; 1464 m_dbgGuiVT = 0; 1465 } 1466 } 1467 1468 void UIMachineLogic::dbgAdjustRelativePos() 1469 { 1470 if (m_dbgGui) 1471 { 1472 QRect rct = machineWindowWrapper()->machineWindow()->frameGeometry(); 1473 m_dbgGuiVT->pfnAdjustRelativePos(m_dbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 1474 } 1475 } 1476 #endif 1477 1478 #if 0 // TODO: Where to move that? 1479 # ifdef Q_WS_MAC 1480 void UIMachineLogic::fadeToBlack() 1481 { 1482 /* Fade to black */ 1483 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken); 1484 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); 1485 } 1486 void UIMachineLogic::fadeToNormal() 1487 { 1488 /* Fade back to the normal gamma */ 1489 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 1490 CGReleaseDisplayFadeReservation (mFadeToken); 1491 mConsole->setMouseCoalescingEnabled (true); 1492 } 1493 # endif 1494 bool UIMachineLogic::toggleFullscreenMode (bool aOn, bool aSeamless) 3257 1495 { 3258 1496 /* Please note: For some platforms like the Mac, the calling order of the … … 3326 1564 if (!aSeamless) 3327 1565 { 3328 /* Fade to black */3329 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken);3330 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true);3331 1566 } 3332 1567 #endif … … 3354 1589 mIsFullscreen = aOn; 3355 1590 mVmAdjustWindowAction->setEnabled (!aOn); 3356 mVmSeamlessAction->setEnabled (!aOn && m IsSeamlessSupported && mIsGraphicsSupported);1591 mVmSeamlessAction->setEnabled (!aOn && m_bIsSeamlessSupported && m_bIsGraphicsSupported); 3357 1592 } 3358 1593 … … 3523 1758 hide(); 3524 1759 #endif 3525 3526 1760 return true; 3527 1761 } 3528 3529 void VBoxConsoleWnd::switchToFullscreen (bool aOn, bool aSeamless) 1762 void UIMachineLogic::switchToFullscreen (bool aOn, bool aSeamless) 3530 1763 { 3531 1764 #ifdef Q_WS_MAC … … 3558 1791 /* Here we are going really fullscreen */ 3559 1792 setWindowState (windowState() ^ Qt::WindowFullScreen); 3560 changePresentationMode (VBoxChangePresentationModeEvent(aOn));1793 sltChangePresentationMode (VBoxChangePresentationModeEvent(aOn)); 3561 1794 } 3562 1795 … … 3571 1804 #endif 3572 1805 } 3573 3574 void VBoxConsoleWnd::setViewInSeamlessMode (const QRect &aTargetRect) 1806 void UIMachineLogic::setViewInSeamlessMode (const QRect &aTargetRect) 3575 1807 { 3576 1808 #ifndef Q_WS_MAC … … 3597 1829 #endif // !Q_WS_MAC 3598 1830 } 3599 3600 /** 3601 * Closes the console view opened by openView(). 3602 * Does nothing if no console view was opened. 3603 */ 3604 void VBoxConsoleWnd::closeView() 3605 { 3606 LogFlowFuncEnter(); 3607 3608 if (!mConsole) 3609 { 3610 LogFlow (("Already closed!\n")); 3611 LogFlowFuncLeave(); 3612 return; 3613 } 3614 3615 mConsole->detach(); 3616 centralWidget()->layout()->removeWidget (mConsole); 3617 delete mConsole; 3618 mConsole = 0; 3619 mSession.Close(); 3620 mSession.detach(); 3621 3622 LogFlowFuncLeave(); 3623 } 3624 3625 #ifdef VBOX_WITH_DEBUGGER_GUI 3626 3627 /** 3628 * Prepare the Debug menu. 3629 */ 3630 void VBoxConsoleWnd::dbgPrepareDebugMenu() 3631 { 3632 /* The "Logging" item. */ 3633 bool fEnabled = false; 3634 bool fChecked = false; 3635 CConsole console = mSession.GetConsole(); 3636 if (console.isOk()) 3637 { 3638 CMachineDebugger cdebugger = console.GetDebugger(); 3639 if (console.isOk()) 3640 { 3641 fEnabled = true; 3642 fChecked = cdebugger.GetLogEnabled() != FALSE; 3643 } 3644 } 3645 if (fEnabled != mDbgLoggingAction->isEnabled()) 3646 mDbgLoggingAction->setEnabled (fEnabled); 3647 if (fChecked != mDbgLoggingAction->isChecked()) 3648 mDbgLoggingAction->setChecked (fChecked); 3649 } 3650 3651 /** 3652 * Called when the Debug->Statistics... menu item is selected. 3653 */ 3654 void VBoxConsoleWnd::dbgShowStatistics() 3655 { 3656 if (dbgCreated()) 3657 mDbgGuiVT->pfnShowStatistics (mDbgGui); 3658 } 3659 3660 /** 3661 * Called when the Debug->Command Line... menu item is selected. 3662 */ 3663 void VBoxConsoleWnd::dbgShowCommandLine() 3664 { 3665 if (dbgCreated()) 3666 mDbgGuiVT->pfnShowCommandLine (mDbgGui); 3667 } 3668 3669 /** 3670 * Called when the Debug->Logging menu item is selected. 3671 */ 3672 void VBoxConsoleWnd::dbgLoggingToggled (bool aState) 3673 { 3674 NOREF(aState); 3675 CConsole console = mSession.GetConsole(); 3676 if (console.isOk()) 3677 { 3678 CMachineDebugger cdebugger = console.GetDebugger(); 3679 if (console.isOk()) 3680 cdebugger.SetLogEnabled (aState); 3681 } 3682 } 3683 3684 /** 3685 * Ensures that the debugger GUI instance is ready. 3686 * 3687 * @returns true if instance is fine and dandy. 3688 * @returns flase if it's not. 3689 */ 3690 bool VBoxConsoleWnd::dbgCreated() 3691 { 3692 if (mDbgGui) 3693 return true; 3694 3695 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 3696 if (hLdrMod == NIL_RTLDRMOD) 3697 return false; 3698 3699 PFNDBGGUICREATE pfnGuiCreate; 3700 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 3701 if (RT_SUCCESS (rc)) 3702 { 3703 ISession *pISession = mSession.raw(); 3704 rc = pfnGuiCreate (pISession, &mDbgGui, &mDbgGuiVT); 3705 if (RT_SUCCESS (rc)) 3706 { 3707 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (mDbgGuiVT->u32Version, DBGGUIVT_VERSION) || 3708 mDbgGuiVT->u32EndVersion == mDbgGuiVT->u32Version) 3709 { 3710 mDbgGuiVT->pfnSetParent (mDbgGui, (QWidget*) this); 3711 mDbgGuiVT->pfnSetMenu (mDbgGui, (QMenu*) mDbgMenu); 3712 dbgAdjustRelativePos(); 3713 return true; 3714 } 3715 3716 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 3717 mDbgGuiVT->u32Version, mDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3718 } 3719 else 3720 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 3721 } 3722 else 3723 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 3724 3725 mDbgGui = 0; 3726 mDbgGuiVT = 0; 3727 return false; 3728 } 3729 3730 /** 3731 * Destroys the debugger GUI instacne if it has been created. 3732 */ 3733 void VBoxConsoleWnd::dbgDestroy() 3734 { 3735 if (mDbgGui) 3736 { 3737 mDbgGuiVT->pfnDestroy (mDbgGui); 3738 mDbgGui = 0; 3739 mDbgGuiVT = 0; 3740 } 3741 } 3742 3743 /** 3744 * Tells the debugger GUI that the console window has moved or been resized. 3745 */ 3746 void VBoxConsoleWnd::dbgAdjustRelativePos() 3747 { 3748 if (mDbgGui) 3749 { 3750 QRect rct = frameGeometry(); 3751 mDbgGuiVT->pfnAdjustRelativePos (mDbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 3752 } 3753 } 3754 3755 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3756 3757 VBoxNetworkDialog::VBoxNetworkDialog (QWidget *aParent, CSession &aSession) 3758 : QIWithRetranslateUI <QDialog> (aParent) 3759 , mSettings (0) 3760 , mSession (aSession) 3761 { 3762 setModal (true); 3763 /* Setup Dialog's options */ 3764 setWindowIcon (QIcon (":/nw_16px.png")); 3765 setSizeGripEnabled (true); 3766 3767 /* Setup main dialog's layout */ 3768 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3769 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3770 mainLayout->setSpacing (10); 3771 3772 /* Setup settings layout */ 3773 mSettings = new VBoxVMSettingsNetworkPage (true); 3774 mSettings->setOrderAfter (this); 3775 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3776 mSettings->getFrom (aSession.GetMachine()); 3777 mainLayout->addWidget (mSettings); 3778 3779 /* Setup button's layout */ 3780 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3781 3782 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3783 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3784 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3785 mainLayout->addWidget (buttonBox); 3786 3787 retranslateUi(); 3788 } 3789 3790 void VBoxNetworkDialog::retranslateUi() 3791 { 3792 setWindowTitle (tr ("Network Adapters")); 3793 } 3794 3795 void VBoxNetworkDialog::accept() 3796 { 3797 mSettings->putBackTo(); 3798 CMachine machine = mSession.GetMachine(); 3799 machine.SaveSettings(); 3800 if (!machine.isOk()) 3801 vboxProblem().cannotSaveMachineSettings (machine); 3802 QDialog::accept(); 3803 } 3804 3805 void VBoxNetworkDialog::showEvent (QShowEvent *aEvent) 3806 { 3807 resize (450, 300); 3808 VBoxGlobal::centerWidget (this, parentWidget()); 3809 setMinimumWidth (400); 3810 QDialog::showEvent (aEvent); 3811 } 3812 3813 VBoxSFDialog::VBoxSFDialog (QWidget *aParent, CSession &aSession) 3814 : QIWithRetranslateUI <QDialog> (aParent) 3815 , mSettings (0) 3816 , mSession (aSession) 3817 { 3818 setModal (true); 3819 /* Setup Dialog's options */ 3820 setWindowIcon (QIcon (":/select_file_16px.png")); 3821 setSizeGripEnabled (true); 3822 3823 /* Setup main dialog's layout */ 3824 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3825 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3826 mainLayout->setSpacing (10); 3827 3828 /* Setup settings layout */ 3829 mSettings = new VBoxVMSettingsSF (MachineType | ConsoleType, this); 3830 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3831 mSettings->getFromConsole (aSession.GetConsole()); 3832 mSettings->getFromMachine (aSession.GetMachine()); 3833 mainLayout->addWidget (mSettings); 3834 3835 /* Setup button's layout */ 3836 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3837 3838 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3839 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3840 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3841 mainLayout->addWidget (buttonBox); 3842 3843 retranslateUi(); 3844 } 3845 3846 void VBoxSFDialog::retranslateUi() 3847 { 3848 setWindowTitle (tr ("Shared Folders")); 3849 } 3850 3851 void VBoxSFDialog::accept() 3852 { 3853 mSettings->putBackToConsole(); 3854 mSettings->putBackToMachine(); 3855 CMachine machine = mSession.GetMachine(); 3856 machine.SaveSettings(); 3857 if (!machine.isOk()) 3858 vboxProblem().cannotSaveMachineSettings (machine); 3859 QDialog::accept(); 3860 } 3861 3862 void VBoxSFDialog::showEvent (QShowEvent *aEvent) 3863 { 3864 resize (450, 300); 3865 VBoxGlobal::centerWidget (this, parentWidget()); 3866 setMinimumWidth (400); 3867 QDialog::showEvent (aEvent); 3868 } 3869 3870 #include "VBoxConsoleWnd.moc" 1831 #endif 1832 1833 #include "UIMachineLogic.moc" -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass declaration4 * UIMachineLogic class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2009Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef __VBoxConsoleWnd_h__ 24 #define __VBoxConsoleWnd_h__ 25 26 /* Global includes */ 27 #include <QColor> 28 #include <QDialog> 29 #include <QMainWindow> 30 #include <QMap> 31 #include <QMenu> 32 #include <QPointer> 23 #ifndef __UIMachineLogic_h__ 24 #define __UIMachineLogic_h__ 33 25 34 26 /* Local includes */ 35 27 #include "COMDefs.h" 36 #include "QIWithRetranslateUI.h" 37 #include "VBoxProblemReporter.h" 38 #include "VBoxHelpActions.h" 39 28 #include "UIMachineDefs.h" 40 29 #ifdef VBOX_WITH_DEBUGGER_GUI 41 30 # include <VBox/dbggui.h> 42 31 #endif 43 #ifdef Q_WS_MAC44 # include <ApplicationServices/ApplicationServices.h>45 # ifndef QT_MAC_USE_COCOA46 # include <Carbon/Carbon.h>47 # endif /* !QT_MAC_USE_COCOA */48 #endif49 32 50 33 /* Global forwards */ 51 class QAction;52 34 class QActionGroup; 53 class QLabel;54 class QSpacerItem;55 class QIWidgetValidator;56 35 57 36 /* Local forwards */ 58 class QIMenu; 59 class QIStateIndicator; 60 class VBoxChangeDockIconUpdateEvent; 61 class VBoxChangePresentationModeEvent; 62 class VBoxConsoleView; 63 class VBoxMiniToolBar; 64 class VBoxSwitchMenu; 65 class VBoxUSBMenu; 37 class UIActionsPool; 38 class UIMachineWindow; 66 39 67 class VBoxConsoleWnd : public QIWithRetranslateUI2 <QMainWindow>40 class UIMachineLogic : public QObject 68 41 { 69 42 Q_OBJECT; … … 71 44 public: 72 45 73 VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent = 0, Qt::WindowFlags aFlags = Qt::Window); 74 virtual ~VBoxConsoleWnd(); 46 /* Factory function to create required logic sub-child: */ 47 static UIMachineLogic* create(QObject *pParent, 48 const CSession &session, 49 UIActionsPool *pActionsPool, 50 UIVisualStateType visualStateType); 75 51 76 bool isWindowMaximized() const 77 { 78 #ifdef Q_WS_MAC 79 /* On Mac OS X we didn't really jump to the fullscreen mode but 80 * maximize the window. This situation has to be considered when 81 * checking for maximized or fullscreen mode. */ 82 return !isTrueSeamless() && QMainWindow::isMaximized(); 83 #else /* Q_WS_MAC */ 84 return QMainWindow::isMaximized(); 85 #endif /* Q_WS_MAC */ 86 } 87 bool isWindowFullScreen() const 88 { 89 #ifdef Q_WS_MAC 90 /* On Mac OS X we didn't really jump to the fullscreen mode but 91 * maximize the window. This situation has to be considered when 92 * checking for maximized or fullscreen mode. */ 93 return isTrueFullscreen() || isTrueSeamless(); 94 #else /* Q_WS_MAC */ 95 return QMainWindow::isFullScreen(); 96 #endif /* Q_WS_MAC */ 97 } 98 bool isTrueFullscreen() const { return mIsFullscreen; } 99 bool isTrueSeamless() const { return mIsSeamless; } 52 /* Public getters: */ 53 CSession& session() { return m_session; } 54 UIActionsPool* actionsPool() { return m_pActionsPool; } 55 KMachineState machineState() const { return m_machineState; } 56 UIVisualStateType visualStateType() const { return m_visualStateType; } 57 bool isPaused() const { return m_machineState == KMachineState_Paused || m_machineState == KMachineState_TeleportingPausedVM; } 100 58 101 KMachineState machineState() const { return mMachineState; } 102 103 bool openView (const CSession &aSession); 104 105 void setMouseIntegrationLocked (bool aDisabled); 106 107 void popupMainMenu (bool aCenter); 108 109 void installGuestAdditionsFrom (const QString &aSource); 110 111 void setMask (const QRegion &aRegion); 112 void clearMask(); 113 114 /* informs that the guest display is resized */ 115 void onDisplayResize (ulong aHeight, ulong aWidth); 116 117 #ifdef VBOX_WITH_VIDEOHWACCEL 118 /* used for obtaining the extradata settings */ 119 CSession &session() { return mSession; } 120 #endif 121 signals: 122 123 void closing(); 59 /* Public setters: */ 60 bool pause(bool bPaused); 124 61 125 62 protected: 126 63 127 bool event (QEvent *aEvent); 128 void closeEvent (QCloseEvent *aEvent); 129 #ifdef Q_WS_X11 130 bool x11Event (XEvent *aEvent); 131 #endif 64 /* Common machine logic constructor: */ 65 UIMachineLogic(QObject *pParent, 66 const CSession &session, 67 UIActionsPool *pActionsPool, 68 UIVisualStateType visualStateType); 69 /* Common machine logic destructor: */ 70 virtual ~UIMachineLogic(); 132 71 133 void retranslateUi(); 72 /* Update routines: */ 73 virtual void updateAppearanceOf(int iElement); 74 75 /* Protected getters: */ 76 UIMachineWindow* machineWindowWrapper() { return m_pMachineWindowContainer; } 77 bool isFirstTimeStarted() const { return m_bIsFirstTimeStarted; } 78 bool isPreventAutoClose() const { return m_bIsPreventAutoClose; } 79 80 /* Pretected setters: */ 81 void setMachineState(KMachineState state) { m_machineState = state; } 82 void setPreventAutoClose(bool bIsPreventAutoClose) { m_bIsPreventAutoClose = bIsPreventAutoClose; } 83 void setOpenViewFinished(bool bIsOpenViewFinished) { m_bIsOpenViewFinished = bIsOpenViewFinished; } 84 85 /* Protected variables: */ 86 UIMachineWindow *m_pMachineWindowContainer; 134 87 135 88 private slots: 136 89 137 void finalizeOpenView(); 138 void tryClose(); 90 /* "Machine" menu funtionality */ 91 void sltAdjustWindow(); 92 void sltToggleMouseIntegration(bool bOff); 93 void sltTypeCAD(); 94 #ifdef Q_WS_X11 95 void sltTypeCABS(); 96 #endif 97 void sltTakeSnapshot(); 98 void sltShowInformationDialog(); 99 void sltReset(); 100 void sltPause(bool aOn); 101 void sltACPIShutdown(); 102 void sltClose(); 139 103 140 void vmFullscreen (bool aOn); 141 void vmSeamless (bool aOn); 142 void vmAutoresizeGuest (bool aOn); 143 void vmAdjustWindow(); 144 void vmDisableMouseIntegration (bool aOff); 145 void vmTypeCAD(); 146 #ifdef Q_WS_X11 147 void vmTypeCABS(); 148 #endif 149 void vmTakeSnapshot(); 150 void vmShowInfoDialog(); 151 void vmReset(); 152 void vmPause (bool aOn); 153 void vmACPIShutdown(); 154 void vmClose(); 155 156 void devicesSwitchVrdp (bool aOn); 157 void devicesOpenNetworkDialog(); 158 void devicesOpenSFDialog(); 159 void devicesInstallGuestAdditions(); 160 161 void prepareStorageMenu(); 162 void prepareNetworkMenu(); 163 void prepareSFMenu(); 164 165 void mountMedium(); 166 void switchUSB (QAction *aAction); 167 168 void showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent); 169 170 void updateDeviceLights(); 171 void updateMachineState (KMachineState aState); 172 void updateMouseState (int aState); 173 void updateAdditionsState (const QString &aVersion, bool aActive, 174 bool aSeamlessSupported, bool aGraphicsSupported); 175 void updateNetworkAdaptersState(); 176 void updateUsbState(); 177 void updateMediaDriveState (VBoxDefs::MediumType aType); 178 void updateSharedFoldersState(); 179 180 void onExitFullscreen(); 181 void unlockActionsSwitch(); 182 183 void mtExitMode(); 184 void mtCloseVM(); 185 void mtMaskUpdate(); 186 187 void changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent); 188 void changePresentationMode (const VBoxChangePresentationModeEvent &aEvent); 189 void processGlobalSettingChange (const char *aPublicName, const char *aName); 104 /* "Device" menu funtionality */ 105 void sltPrepareStorageMenu(); 106 void sltMountStorageMedium(); 107 void sltOpenNetworkAdaptersDialog(); 108 void sltOpenSharedFoldersDialog(); 109 void sltPrepareUSBMenu(); 110 void sltAttachUSBDevice(); 111 void sltSwitchVrdp(bool bOn); 112 void sltInstallGuestAdditions(); 190 113 191 114 #ifdef VBOX_WITH_DEBUGGER_GUI 192 void dbgPrepareDebugMenu();193 void dbgShowStatistics();194 void dbgShowCommandLine();195 void dbgLoggingToggled (bool aBool);115 void sltPrepareDebugMenu(); 116 void sltShowDebugStatistics(); 117 void sltShowDebugCommandLine(); 118 void sltLoggingToggled(bool); 196 119 #endif 120 121 /* Machine state change handler */ 122 void sltUpdateMachineState(KMachineState machineState); 123 /* Guest Additions state change handler */ 124 void sltUpdateAdditionsState(const QString &strVersion, bool bActive, bool bSeamlessSupported, bool bGraphicsSupported); 125 /* Mouse Integration state change handler */ 126 void sltUpdateMouseState(int iState); 197 127 198 128 private: 199 129 200 enum /* Stuff */ 201 { 202 HardDiskStuff = 0x01, 203 DVDStuff = 0x02, 204 FloppyStuff = 0x04, 205 PauseAction = 0x08, 206 NetworkStuff = 0x10, 207 DisableMouseIntegrAction = 0x20, 208 Caption = 0x40, 209 USBStuff = 0x80, 210 VRDPStuff = 0x100, 211 SharedFolderStuff = 0x200, 212 VirtualizationStuff = 0x400, 213 AllStuff = 0xFFFF, 214 }; 130 /* Prepare helpers: */ 131 void prepareActionGroups(); 132 void prepareActionConnections(); 133 void prepareRequiredFeatures(); 134 void loadLogicSettings(); 215 135 216 void checkRequiredFeatures(); 217 void activateUICustomizations(); 136 /* Cleanup helpers: */ 137 void saveLogicSettings(); 138 //void cleanupRequiredFeatures(); 139 //void cleanupActionConnections(); 140 //void cleanupActionGroups(); 218 141 219 void updateAppearanceOf (int aElement); 220 221 bool toggleFullscreenMode (bool aOn, bool aSeamless); 222 void switchToFullscreen (bool aOn, bool aSeamless); 223 void setViewInSeamlessMode (const QRect &aTargetRect); 224 225 void closeView(); 226 142 /* Utility functions: */ 143 void installGuestAdditionsFrom(const QString &strSource); 144 static int searchMaxSnapshotIndex(const CMachine &machine, const CSnapshot &snapshot, const QString &strNameTemplate); 227 145 #ifdef VBOX_WITH_DEBUGGER_GUI 228 146 bool dbgCreated(); … … 231 149 #endif 232 150 233 /* COM Variables */ 234 CSession mSession; 151 #if 0 // TODO: Where to move that? 152 # ifdef Q_WS_MAC 153 void fadeToBlack(); 154 void fadeToNormal(); 155 # endif 156 bool toggleFullscreenMode(bool aOn, bool aSeamless); 157 void switchToFullscreen(bool aOn, bool aSeamless); 158 void setViewInSeamlessMode(const QRect &aTargetRect); 159 #endif 235 160 236 /* Machine State */ 237 KMachineState mMachineState; 161 /* Private variables: */ 162 CSession m_session; 163 UIActionsPool *m_pActionsPool; 164 KMachineState m_machineState; 165 UIVisualStateType m_visualStateType; 238 166 239 /* Window Variables */ 240 QString mCaptionPrefix; 241 int mConsoleStyle; 167 QActionGroup *m_pRunningActions; 168 QActionGroup *m_pRunningOrPausedActions; 242 169 243 /* Menu items */ 244 QIMenu *mMainMenu; 245 QMenu *mVMMenu; 246 QMenu *mVMMenuMini; 247 QMenu *mDevicesMenu; 248 QMenu *mDevicesCDMenu; 249 QMenu *mDevicesFDMenu; 250 QMenu *mDevicesNetworkMenu; 251 QMenu *mDevicesSFMenu; 252 VBoxUSBMenu *mDevicesUSBMenu; 253 VBoxSwitchMenu *mVmDisMouseIntegrMenu; 254 #if 0 /* todo: allow to setup */ 255 VBoxSwitchMenu *mDevicesVRDPMenu; 256 VBoxSwitchMenu *mVmAutoresizeMenu; 257 #endif 258 #ifdef VBOX_WITH_DEBUGGER_GUI 259 QMenu *mDbgMenu; 260 #endif 261 QMenu *mHelpMenu; 262 263 QActionGroup *mRunningActions; 264 QActionGroup *mRunningOrPausedActions; 265 266 /* Machine actions */ 267 QAction *mVmFullscreenAction; 268 QAction *mVmSeamlessAction; 269 QAction *mVmAutoresizeGuestAction; 270 QAction *mVmAdjustWindowAction; 271 QAction *mVmDisableMouseIntegrAction; 272 QAction *mVmTypeCADAction; 273 #ifdef Q_WS_X11 274 QAction *mVmTypeCABSAction; 275 #endif 276 QAction *mVmTakeSnapshotAction; 277 QAction *mVmShowInformationDlgAction; 278 QAction *mVmResetAction; 279 QAction *mVmPauseAction; 280 QAction *mVmACPIShutdownAction; 281 QAction *mVmCloseAction; 282 283 /* Devices actions */ 284 QAction *mDevicesNetworkDialogAction; 285 QAction *mDevicesSFDialogAction; 286 QAction *mDevicesSwitchVrdpSeparator; 287 QAction *mDevicesSwitchVrdpAction; 288 QAction *mDevicesInstallGuestToolsAction; 170 bool m_bIsFirstTimeStarted : 1; 171 bool m_bIsOpenViewFinished : 1; 172 bool m_bIsGraphicsSupported : 1; 173 bool m_bIsSeamlessSupported : 1; 174 bool m_bIsAutoSaveMedia : 1; 175 bool m_bIsPreventAutoClose : 1; 289 176 290 177 #ifdef VBOX_WITH_DEBUGGER_GUI 291 /* Debugger actions*/292 QAction *mDbgStatisticsAction;293 QAction *mDbgCommandLineAction;294 QAction *mDbgLoggingAction;178 /* The handle to the debugger gui: */ 179 PDBGGUI m_dbgGui; 180 /* The virtual method table for the debugger GUI: */ 181 PCDBGGUIVT m_dbgGuiVT; 295 182 #endif 296 297 /* Help actions */298 VBoxHelpActions mHelpActions;299 300 /* Widgets */301 VBoxConsoleView *mConsole;302 VBoxMiniToolBar *mMiniToolBar;303 #ifdef VBOX_WITH_DEBUGGER_GUI304 /** The handle to the debugger gui. */305 PDBGGUI mDbgGui;306 /** The virtual method table for the debugger GUI. */307 PCDBGGUIVT mDbgGuiVT;308 #endif309 310 /* Timer to update LEDs */311 QTimer *mIdleTimer;312 313 /* LEDs */314 QIStateIndicator *mHDLed;315 QIStateIndicator *mCDLed;316 #if 0 /* todo: allow to setup */317 QIStateIndicator *mFDLed;318 #endif319 QIStateIndicator *mNetLed;320 QIStateIndicator *mUSBLed;321 QIStateIndicator *mSFLed;322 QIStateIndicator *mVirtLed;323 QIStateIndicator *mMouseLed;324 QIStateIndicator *mHostkeyLed;325 QWidget *mHostkeyLedContainer;326 QLabel *mHostkeyName;327 #if 0 /* todo: allow to setup */328 QIStateIndicator *mVrdpLed;329 QIStateIndicator *mAutoresizeLed;330 #endif331 332 /* Normal Mode */333 QRect mNormalGeo;334 335 /* Fullscreen/Seamless Mode */336 QList < QPointer <QWidget> > mHiddenChildren;337 QSpacerItem *mShiftingSpacerLeft;338 QSpacerItem *mShiftingSpacerTop;339 QSpacerItem *mShiftingSpacerRight;340 QSpacerItem *mShiftingSpacerBottom;341 QPalette mErasePalette;342 QSize mPrevMinSize;343 QSize mMaskShift;344 QRegion mStrictedRegion;345 #ifdef Q_WS_WIN346 QRegion mPrevRegion;347 #endif348 #ifdef Q_WS_MAC349 //QRegion mCurrRegion;350 # ifndef QT_MAC_USE_COCOA351 //EventHandlerRef mDarwinRegionEventHandlerRef;352 # endif353 /* For seamless maximizing */354 QRect mNormalGeometry;355 Qt::WindowFlags mSavedFlags;356 /* For the fade effect if the the window goes fullscreen */357 CGDisplayFadeReservationToken mFadeToken;358 #endif359 360 /* Different bool flags */361 bool mIsOpenViewFinished : 1;362 bool mIsFirstTimeStarted : 1;363 bool mIsAutoSaveMedia : 1;364 bool mNoAutoClose : 1;365 bool mIsFullscreen : 1;366 bool mIsSeamless : 1;367 bool mIsSeamlessSupported : 1;368 bool mIsGraphicsSupported : 1;369 bool mIsWaitingModeResize : 1;370 bool mWasMax : 1;371 183 }; 372 184 373 /* We want to make the first action highlighted but not 374 * selected, but Qt makes the both or neither one of this, 375 * so, just move the focus to the next eligible object, 376 * which will be the first menu action. This little 377 * subclass made only for that purpose. */ 378 class QIMenu : public QMenu 379 { 380 Q_OBJECT; 381 382 public: 383 384 QIMenu (QWidget *aParent) : QMenu (aParent) {} 385 386 void selectFirstAction() { QMenu::focusNextChild(); } 387 }; 388 389 class VBoxSettingsPage; 390 class VBoxNetworkDialog : public QIWithRetranslateUI <QDialog> 391 { 392 Q_OBJECT; 393 394 public: 395 396 VBoxNetworkDialog (QWidget *aParent, CSession &aSession); 397 398 protected: 399 400 void retranslateUi(); 401 402 protected slots: 403 404 virtual void accept(); 405 406 protected: 407 408 void showEvent (QShowEvent *aEvent); 409 410 private: 411 412 VBoxSettingsPage *mSettings; 413 CSession &mSession; 414 }; 415 416 class VBoxVMSettingsSF; 417 class VBoxSFDialog : public QIWithRetranslateUI <QDialog> 418 { 419 Q_OBJECT; 420 421 public: 422 423 VBoxSFDialog (QWidget *aParent, CSession &aSession); 424 425 protected: 426 427 void retranslateUi(); 428 429 protected slots: 430 431 virtual void accept(); 432 433 protected: 434 435 void showEvent (QShowEvent *aEvent); 436 437 private: 438 439 VBoxVMSettingsSF *mSettings; 440 CSession &mSession; 441 }; 442 443 #endif // __VBoxConsoleWnd_h__ 185 #endif // __UIMachineLogic_h__ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleView class implementation4 * UIMachineView class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 2 2006-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 24 # include "precomp.h" 25 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 23 /* Global includes */ 24 #include <QDesktopWidget> 25 #include <QTimer> 26 #include <QPainter> 27 #include <QScrollBar> 26 28 #include <VBox/VBoxVideo.h> 27 29 28 #include "VBoxConsoleView.h" 29 #include "VBoxConsoleWnd.h" 30 #include "VBoxUtils.h" 31 32 #include "VBoxFrameBuffer.h" 30 /* Local includes */ 33 31 #include "VBoxGlobal.h" 34 32 #include "VBoxProblemReporter.h" 33 #include "UIFrameBuffer.h" 34 #include "UIActionsPool.h" 35 #include "UIMachineLogic.h" 36 #include "UIMachineWindow.h" 37 #include "UIMachineView.h" 38 #include "UIMachineViewNormal.h" 35 39 36 40 #ifdef Q_WS_PM 37 #include "QIHotKeyEdit.h" 38 #endif 39 40 /* Qt includes */ 41 #include <QMenuBar> 42 #include <QDesktopWidget> 43 #include <QTimer> 44 #include <QStatusBar> 45 #include <QPainter> 46 #include <QBitmap> 47 48 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ /** @todo Move this further down! Requires some cleanup below though, so later. */ 41 # include "QIHotKeyEdit.h" 42 #endif 49 43 50 44 #ifdef Q_WS_WIN 51 // VBox/cdefs.h defines these:52 45 #undef LOWORD 53 46 #undef HIWORD … … 58 51 59 52 #ifdef Q_WS_X11 60 #include <QX11Info> 61 // We need to capture some X11 events directly which 62 // requires the XEvent structure to be defined. However, 63 // including the Xlib header file will cause some nasty 64 // conflicts with Qt. Therefore we use the following hack 65 // to redefine those conflicting identifiers. 66 #define XK_XKB_KEYS 67 #define XK_MISCELLANY 68 #include <X11/Xlib.h> 69 #include <X11/Xutil.h> 70 #include <X11/XKBlib.h> 71 #include <X11/keysym.h> 72 #ifdef KeyPress 53 # include <QX11Info> 54 # define XK_XKB_KEYS 55 # define XK_MISCELLANY 56 # include <X11/XKBlib.h> 57 # include <X11/keysym.h> 58 # ifdef KeyPress 73 59 const int XFocusOut = FocusOut; 74 60 const int XFocusIn = FocusIn; 75 61 const int XKeyPress = KeyPress; 76 62 const int XKeyRelease = KeyRelease; 77 # undef KeyRelease78 # undef KeyPress79 # undef FocusOut80 # undef FocusIn81 # endif82 # include "XKeyboard.h"83 # ifndef VBOX_WITHOUT_XCURSOR84 # include <X11/Xcursor/Xcursor.h>85 # endif86 #endif // Q_WS_X1163 # undef KeyRelease 64 # undef KeyPress 65 # undef FocusOut 66 # undef FocusIn 67 # endif 68 # include "XKeyboard.h" 69 # ifndef VBOX_WITHOUT_XCURSOR 70 # include <X11/Xcursor/Xcursor.h> 71 # endif 72 #endif 87 73 88 74 #if defined (Q_WS_MAC) … … 98 84 #endif /* defined (Q_WS_MAC) */ 99 85 100 #if defined (Q_WS_WIN32)101 102 static HHOOK gKbdHook = NULL;103 static VBoxConsoleView *gView = 0;104 105 LRESULT CALLBACK VBoxConsoleView::lowLevelKeyboardProc (int nCode,106 WPARAM wParam, LPARAM lParam)107 {108 Assert (gView);109 if (gView && nCode == HC_ACTION &&110 gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam))111 return 1;112 113 return CallNextHookEx (NULL, nCode, wParam, lParam);114 }115 116 #endif117 118 #if defined (Q_WS_MAC)119 # if defined (QT_MAC_USE_COCOA)120 /**121 * Event handler callback for Mac OS X, Cocoa variant.122 *123 * (Registered with and called from VBoxCocoaApplication.)124 *125 * @returns true if the event should be dropped, false if it should be passed126 * along.127 * @param pvCocoaEvent The Cocoa event object.128 * @param pvCarbonEvent The Carbon event object reference.129 * @param pvUser The user argument.130 */131 /* static */132 bool VBoxConsoleView::darwinEventHandlerProc (const void *pvCocoaEvent,133 const void *pvCarbonEvent,134 void *pvUser)135 {136 VBoxConsoleView *view = (VBoxConsoleView *)pvUser;137 EventRef inEvent = (EventRef)pvCarbonEvent;138 UInt32 eventClass = ::GetEventClass (inEvent);139 140 #if 0141 /* For debugging events. */142 if (eventClass != 'cute')143 ::VBoxCocoaApplication_printEvent ("view: ", pvCocoaEvent);144 #endif145 /* Check if this is an application key combo. In that case we will not pass146 the event to the guest, but let the host process it. */147 if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent))148 return false;149 150 /*151 * All keyboard class events needs to be handled.152 */153 if (eventClass == kEventClassKeyboard)154 {155 if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))156 return true;157 }158 /* Pass the event along. */159 return false;160 }161 162 # elif !defined (VBOX_WITH_HACKED_QT)163 /**164 * Event handler callback for Mac OS X.165 */166 /* static */167 pascal OSStatus VBoxConsoleView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef,168 EventRef inEvent, void *inUserData)169 {170 VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);171 UInt32 eventClass = ::GetEventClass (inEvent);172 173 /* For debugging events */174 /*175 if (eventClass != 'cute')176 ::darwinDebugPrintEvent ("view: ", inEvent);177 */178 179 /* Not sure but this seems an triggered event if the spotlight searchbar is180 * displayed. So flag that the host key isn't pressed alone. */181 if ( eventClass == 'cgs '182 && view->mIsHostkeyPressed183 && ::GetEventKind (inEvent) == 0x15)184 view->mIsHostkeyAlone = false;185 186 if (eventClass == kEventClassKeyboard)187 {188 if (view->darwinKeyboardEvent (NULL, inEvent))189 return 0;190 }191 /*192 * Command-H and Command-Q aren't properly disabled yet, and it's still193 * possible to use the left command key to invoke them when the keyboard194 * is captured. We discard the events these if the keyboard is captured195 * as a half measure to prevent unexpected behaviour. However, we don't196 * get any key down/up events, so these combinations are dead to the guest...197 */198 else if (eventClass == kEventClassCommand)199 {200 if (view->mKbdCaptured)201 return 0;202 }203 return ::CallNextEventHandler (inHandlerCallRef, inEvent);204 }205 206 # else /* VBOX_WITH_HACKED_QT */207 /**208 * Event handler callback for Mac OS X.209 */210 /* static */211 bool VBoxConsoleView::macEventFilter (EventRef inEvent, void *inUserData)212 {213 VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);214 UInt32 eventClass = ::GetEventClass (inEvent);215 UInt32 eventKind = ::GetEventKind (inEvent);216 217 /* For debugging events */218 /*219 if (!(eventClass == 'cute'))220 ::darwinDebugPrintEvent ("view: ", inEvent);221 */222 223 /* Not sure but this seems an triggered event if the spotlight searchbar is224 * displayed. So flag that the host key isn't pressed alone. */225 if (eventClass == 'cgs ' && eventKind == 0x15 &&226 view->mIsHostkeyPressed)227 view->mIsHostkeyAlone = false;228 229 if (eventClass == kEventClassKeyboard)230 {231 if (view->darwinKeyboardEvent (NULL, inEvent))232 return true;233 }234 return false;235 }236 # endif /* VBOX_WITH_HACKED_QT */237 238 #endif /* Q_WS_MAC */239 240 86 /** Guest mouse pointer shape change event. */ 241 87 class MousePointerChangeEvent : public QEvent 242 88 { 243 89 public: 244 MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot, 245 uint width, uint height, 246 const uchar *shape) : 247 QEvent ((QEvent::Type) VBoxDefs::MousePointerChangeEventType), 248 vis (visible), alph (alpha), xh (xhot), yh (yhot), w (width), h (height), 249 data (NULL) 250 { 251 // make a copy of shape 90 91 MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot, uint width, uint height, const uchar *shape) 92 : QEvent((QEvent::Type)VBoxDefs::MousePointerChangeEventType) 93 , vis(visible), alph(alpha), xh(xhot), yh(yhot), w(width), h(height), data(0) 94 { 252 95 uint dataSize = ((((width + 7) / 8 * height) + 3) & ~3) + width * 4 * height; 253 96 254 if (shape) { 255 data = new uchar [dataSize]; 256 memcpy ((void *) data, (void *) shape, dataSize); 257 } 258 } 97 if (shape) 98 { 99 data = new uchar[dataSize]; 100 memcpy((void*)data, (void*)shape, dataSize); 101 } 102 } 103 259 104 ~MousePointerChangeEvent() 260 105 { 261 106 if (data) delete[] data; 262 107 } 108 263 109 bool isVisible() const { return vis; } 264 110 bool hasAlpha() const { return alph; } … … 268 114 uint height() const { return h; } 269 115 const uchar *shapeData() const { return data; } 116 270 117 private: 118 271 119 bool vis, alph; 272 120 uint xh, yh, w, h; … … 278 126 { 279 127 public: 280 MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor) : 281 QEvent ((QEvent::Type) VBoxDefs::MouseCapabilityEventType), 282 can_abs (supportsAbsolute), 283 needs_host_cursor (needsHostCursor) {} 128 129 MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor) 130 : QEvent((QEvent::Type) VBoxDefs::MouseCapabilityEventType) 131 , can_abs(supportsAbsolute), needs_host_cursor(needsHostCursor) {} 132 284 133 bool supportsAbsolute() const { return can_abs; } 285 134 bool needsHostCursor() const { return needs_host_cursor; } 135 286 136 private: 137 287 138 bool can_abs; 288 139 bool needs_host_cursor; … … 293 144 { 294 145 public: 295 StateChangeEvent (KMachineState state) : 296 QEvent ((QEvent::Type) VBoxDefs::MachineStateChangeEventType), 297 s (state) {} 146 147 StateChangeEvent (KMachineState state) 148 : QEvent((QEvent::Type)VBoxDefs::MachineStateChangeEventType) 149 , s (state) {} 150 298 151 KMachineState machineState() const { return s; } 152 299 153 private: 154 300 155 KMachineState s; 301 156 }; … … 305 160 { 306 161 public: 162 307 163 GuestAdditionsEvent (const QString &aOsTypeId, 308 164 const QString &aAddVersion, 309 165 bool aAddActive, 310 166 bool aSupportsSeamless, 311 bool aSupportsGraphics) : 312 QEvent ((QEvent::Type) VBoxDefs::AdditionsStateChangeEventType), 313 mOsTypeId (aOsTypeId), mAddVersion (aAddVersion), 314 mAddActive (aAddActive), mSupportsSeamless (aSupportsSeamless), 315 mSupportsGraphics (aSupportsGraphics) {} 167 bool aSupportsGraphics) 168 : QEvent((QEvent::Type)VBoxDefs::AdditionsStateChangeEventType) 169 , mOsTypeId(aOsTypeId), mAddVersion(aAddVersion) 170 , mAddActive(aAddActive), mSupportsSeamless(aSupportsSeamless) 171 , mSupportsGraphics (aSupportsGraphics) {} 172 316 173 const QString &osTypeId() const { return mOsTypeId; } 317 174 const QString &additionVersion() const { return mAddVersion; } … … 319 176 bool supportsSeamless() const { return mSupportsSeamless; } 320 177 bool supportsGraphics() const { return mSupportsGraphics; } 178 321 179 private: 180 322 181 QString mOsTypeId; 323 182 QString mAddVersion; … … 331 190 { 332 191 public: 333 MediaDriveChangeEvent (VBoxDefs::MediumType aType) 192 193 MediaDriveChangeEvent(VBoxDefs::MediumType aType) 334 194 : QEvent ((QEvent::Type) VBoxDefs::MediaDriveChangeEventType) 335 195 , mType (aType) {} 336 196 VBoxDefs::MediumType type() const { return mType; } 197 337 198 private: 199 338 200 VBoxDefs::MediumType mType; 339 201 }; … … 343 205 { 344 206 public: 345 ActivateMenuEvent (QAction *aData) : 346 QEvent ((QEvent::Type) VBoxDefs::ActivateMenuEventType), 347 mAction (aData) {} 207 208 ActivateMenuEvent (QAction *aData) 209 : QEvent((QEvent::Type)VBoxDefs::ActivateMenuEventType) 210 , mAction(aData) {} 348 211 QAction *action() const { return mAction; } 212 349 213 private: 214 350 215 QAction *mAction; 351 216 }; … … 355 220 { 356 221 public: 357 RuntimeErrorEvent (bool aFatal, const QString &aErrorID, 358 const QString &aMessage) : 359 QEvent ((QEvent::Type) VBoxDefs::RuntimeErrorEventType), 360 mFatal (aFatal), mErrorID (aErrorID), mMessage (aMessage) {} 222 223 RuntimeErrorEvent(bool aFatal, const QString &aErrorID, const QString &aMessage) 224 : QEvent((QEvent::Type)VBoxDefs::RuntimeErrorEventType) 225 , mFatal(aFatal), mErrorID(aErrorID), mMessage(aMessage) {} 226 361 227 bool fatal() const { return mFatal; } 362 228 QString errorID() const { return mErrorID; } 363 229 QString message() const { return mMessage; } 230 364 231 private: 232 365 233 bool mFatal; 366 234 QString mErrorID; … … 372 240 { 373 241 public: 374 ModifierKeyChangeEvent (bool fNumLock, bool fCapsLock, bool fScrollLock) : 375 QEvent ((QEvent::Type) VBoxDefs::ModifierKeyChangeEventType), 376 mNumLock (fNumLock), mCapsLock (fCapsLock), mScrollLock (fScrollLock) {} 242 243 ModifierKeyChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock) 244 : QEvent((QEvent::Type)VBoxDefs::ModifierKeyChangeEventType) 245 , mNumLock(fNumLock), mCapsLock(fCapsLock), mScrollLock(fScrollLock) {} 246 377 247 bool numLock() const { return mNumLock; } 378 248 bool capsLock() const { return mCapsLock; } 379 249 bool scrollLock() const { return mScrollLock; } 250 380 251 private: 252 381 253 bool mNumLock, mCapsLock, mScrollLock; 382 254 }; … … 386 258 { 387 259 public: 388 NetworkAdapterChangeEvent (INetworkAdapter *aAdapter) : 389 QEvent ((QEvent::Type) VBoxDefs::NetworkAdapterChangeEventType), 390 mAdapter (aAdapter) {} 260 261 NetworkAdapterChangeEvent(INetworkAdapter *aAdapter) 262 : QEvent((QEvent::Type)VBoxDefs::NetworkAdapterChangeEventType) 263 , mAdapter(aAdapter) {} 264 391 265 INetworkAdapter* networkAdapter() { return mAdapter; } 266 392 267 private: 268 393 269 INetworkAdapter *mAdapter; 394 270 }; … … 398 274 { 399 275 public: 276 400 277 USBControllerStateChangeEvent() 401 : QEvent ((QEvent::Type)VBoxDefs::USBCtlStateChangeEventType) {}278 : QEvent((QEvent::Type)VBoxDefs::USBCtlStateChangeEventType) {} 402 279 }; 403 280 … … 406 283 { 407 284 public: 408 USBDeviceStateChangeEvent (const CUSBDevice &aDevice, bool aAttached, 409 const CVirtualBoxErrorInfo &aError) : 410 QEvent ((QEvent::Type) VBoxDefs::USBDeviceStateChangeEventType), 411 mDevice (aDevice), mAttached (aAttached), mError (aError) {} 285 286 USBDeviceStateChangeEvent(const CUSBDevice &aDevice, bool aAttached, const CVirtualBoxErrorInfo &aError) 287 : QEvent((QEvent::Type)VBoxDefs::USBDeviceStateChangeEventType) 288 , mDevice(aDevice), mAttached(aAttached), mError(aError) {} 289 412 290 CUSBDevice device() const { return mDevice; } 413 291 bool attached() const { return mAttached; } 414 292 CVirtualBoxErrorInfo error() const { return mError; } 293 415 294 private: 295 416 296 CUSBDevice mDevice; 417 297 bool mAttached; … … 419 299 }; 420 300 421 // 422 // VBoxConsoleCallback class 423 ///////////////////////////////////////////////////////////////////////////// 424 425 class VBoxConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback) 301 class VBoxViewport: public QWidget 426 302 { 427 303 public: 428 304 429 VBoxConsoleCallback (VBoxConsoleView *v) { 305 VBoxViewport(QWidget *pParent) : QWidget(pParent) 306 { 307 /* No need for background drawing */ 308 setAttribute(Qt::WA_OpaquePaintEvent); 309 } 310 311 QPaintEngine *paintEngine() const 312 { 313 if (testAttribute(Qt::WA_PaintOnScreen)) 314 return NULL; 315 else 316 return QWidget::paintEngine(); 317 } 318 }; 319 320 class UIConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback) 321 { 322 public: 323 324 UIConsoleCallback (UIMachineView *v) 325 { 430 326 #if defined (Q_WS_WIN) 431 327 mRefCnt = 0; … … 434 330 } 435 331 436 virtual ~ VBoxConsoleCallback() {}332 virtual ~UIConsoleCallback() {} 437 333 438 334 NS_DECL_ISUPPORTS 439 335 440 336 #if defined (Q_WS_WIN) 441 STDMETHOD_(ULONG, AddRef)() { 442 return ::InterlockedIncrement (&mRefCnt); 337 STDMETHOD_(ULONG, AddRef)() 338 { 339 return ::InterlockedIncrement(&mRefCnt); 443 340 } 444 341 STDMETHOD_(ULONG, Release)() 445 342 { 446 long cnt = ::InterlockedDecrement 343 long cnt = ::InterlockedDecrement(&mRefCnt); 447 344 if (cnt == 0) 448 345 delete this; … … 457 354 BYTE *shape) 458 355 { 459 QApplication::postEvent (mView, 460 new MousePointerChangeEvent (visible, alpha, 461 xhot, yhot, 462 width, height, shape)); 356 QApplication::postEvent(mView, new MousePointerChangeEvent(visible, alpha, xhot, yhot, width, height, shape)); 463 357 return S_OK; 464 358 } … … 466 360 STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor) 467 361 { 468 QApplication::postEvent (mView, 469 new MouseCapabilityEvent (supportsAbsolute, 470 needsHostCursor)); 362 QApplication::postEvent(mView, new MouseCapabilityEvent (supportsAbsolute, needsHostCursor)); 471 363 return S_OK; 472 364 } … … 474 366 STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock) 475 367 { 476 QApplication::postEvent (mView, 477 new ModifierKeyChangeEvent (fNumLock, fCapsLock, 478 fScrollLock)); 368 QApplication::postEvent(mView, new ModifierKeyChangeEvent (fNumLock, fCapsLock, fScrollLock)); 479 369 return S_OK; 480 370 } … … 482 372 STDMETHOD(OnStateChange)(MachineState_T machineState) 483 373 { 484 LogFlowFunc (("machineState=%d\n", machineState)); 485 QApplication::postEvent (mView, 486 new StateChangeEvent ((KMachineState) machineState)); 374 QApplication::postEvent(mView, new StateChangeEvent ((KMachineState) machineState)); 487 375 return S_OK; 488 376 } … … 491 379 { 492 380 CGuest guest = mView->console().GetGuest(); 493 LogFlowFunc (("ver=%s, active=%d\n", 494 guest.GetAdditionsVersion().toLatin1().constData(), 495 guest.GetAdditionsActive())); 496 QApplication::postEvent (mView, 497 new GuestAdditionsEvent ( 498 guest.GetOSTypeId(), 499 guest.GetAdditionsVersion(), 500 guest.GetAdditionsActive(), 501 guest.GetSupportsSeamless(), 502 guest.GetSupportsGraphics())); 381 QApplication::postEvent (mView, new GuestAdditionsEvent(guest.GetOSTypeId(), guest.GetAdditionsVersion(), 382 guest.GetAdditionsActive(), guest.GetSupportsSeamless(), 383 guest.GetSupportsGraphics())); 503 384 return S_OK; 504 385 } … … 506 387 STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter) 507 388 { 508 QApplication::postEvent (mView, 509 new NetworkAdapterChangeEvent (aNetworkAdapter)); 389 QApplication::postEvent (mView, new NetworkAdapterChangeEvent (aNetworkAdapter)); 510 390 return S_OK; 511 391 } … … 513 393 STDMETHOD(OnStorageControllerChange) () 514 394 { 515 /* @todo */ 516 //QApplication::postEvent (mView, 517 // new StorageControllerChangeEvent ()); 395 //QApplication::postEvent(mView, new StorageControllerChangeEvent()); 518 396 return S_OK; 519 397 } … … 525 403 { 526 404 case KDeviceType_Floppy: 527 QApplication::postEvent(mView, 528 new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy)); 405 QApplication::postEvent(mView, new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy)); 529 406 break; 530 407 case KDeviceType_DVD: 531 QApplication::postEvent(mView, 532 new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD)); 408 QApplication::postEvent(mView, new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD)); 533 409 break; 534 410 default: 535 /* @todo later add hard disk change as well */536 411 break; 537 412 } … … 570 445 STDMETHOD(OnUSBControllerChange)() 571 446 { 572 QApplication::postEvent (mView, 573 new USBControllerStateChangeEvent()); 447 QApplication::postEvent (mView, new USBControllerStateChangeEvent()); 574 448 return S_OK; 575 449 } 576 450 577 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached, 578 IVirtualBoxErrorInfo *aError) 579 { 580 QApplication::postEvent (mView, 581 new USBDeviceStateChangeEvent ( 582 CUSBDevice (aDevice), 583 bool (aAttached), 584 CVirtualBoxErrorInfo (aError))); 451 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached, IVirtualBoxErrorInfo *aError) 452 { 453 QApplication::postEvent (mView, new USBDeviceStateChangeEvent(CUSBDevice(aDevice), bool(aAttached), CVirtualBoxErrorInfo(aError))); 585 454 return S_OK; 586 455 } … … 589 458 { 590 459 NOREF(aScope); 591 QApplication::postEvent (mView, 592 new QEvent ((QEvent::Type) 593 VBoxDefs::SharedFolderChangeEventType)); 460 QApplication::postEvent (mView, new QEvent((QEvent::Type)VBoxDefs::SharedFolderChangeEventType)); 594 461 return S_OK; 595 462 } … … 597 464 STDMETHOD(OnRuntimeError)(BOOL fatal, IN_BSTR id, IN_BSTR message) 598 465 { 599 QApplication::postEvent (mView, 600 new RuntimeErrorEvent (!!fatal, 601 QString::fromUtf16 (id), 602 QString::fromUtf16 (message))); 466 QApplication::postEvent (mView, new RuntimeErrorEvent(!!fatal, QString::fromUtf16(id), QString::fromUtf16(message))); 603 467 return S_OK; 604 468 } … … 609 473 return E_POINTER; 610 474 611 /* as long as there is VBoxConsoleView (which creates/destroys us), it612 * can be shown */613 475 *canShow = TRUE; 614 476 return S_OK; … … 633 495 OSErr rc = ::SetFrontProcess (&psn); 634 496 if (!rc) 635 QApplication::postEvent (mView, new QEvent((QEvent::Type)VBoxDefs::ShowWindowEventType));497 QApplication::postEvent(mView, new QEvent((QEvent::Type)VBoxDefs::ShowWindowEventType)); 636 498 else 637 499 { … … 643 505 AssertMsgFailed(("SetFrontProcess -> %#x\n", rc)); 644 506 if (::GetCurrentProcess (&psn)) 645 *winId = RT_MAKE_U64 507 *winId = RT_MAKE_U64(psn.lowLongOfPSN, psn.highLongOfPSN); 646 508 } 647 509 648 510 #else 649 511 /* Return the ID of the top-level console window. */ 650 *winId = (ULONG64) 512 *winId = (ULONG64)mView->window()->winId(); 651 513 #endif 652 514 … … 656 518 protected: 657 519 658 VBoxConsoleView *mView;520 UIMachineView *mView; 659 521 660 522 #if defined (Q_WS_WIN) … … 665 527 666 528 #if !defined (Q_WS_WIN) 667 NS_DECL_CLASSINFO (VBoxConsoleCallback) 668 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (VBoxConsoleCallback, IConsoleCallback) 669 #endif 670 671 class VBoxViewport: public QWidget 672 { 673 public: 674 VBoxViewport (QWidget *aParent) 675 : QWidget (aParent) 676 { 677 /* No need for background drawing */ 678 setAttribute (Qt::WA_OpaquePaintEvent); 679 } 680 virtual QPaintEngine * paintEngine() const 681 { 682 if (testAttribute (Qt::WA_PaintOnScreen)) 683 return NULL; 684 else 685 return QWidget::paintEngine(); 686 } 687 }; 688 689 // 690 // VBoxConsoleView class 691 ///////////////////////////////////////////////////////////////////////////// 692 693 /** @class VBoxConsoleView 694 * 695 * The VBoxConsoleView class is a widget that implements a console 696 * for the running virtual machine. 697 */ 698 699 VBoxConsoleView::VBoxConsoleView (VBoxConsoleWnd *mainWnd, 700 const CConsole &console, 701 VBoxDefs::RenderMode rm, 529 NS_DECL_CLASSINFO(UIConsoleCallback) 530 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIConsoleCallback, IConsoleCallback) 531 #endif 532 533 UIMachineView* UIMachineView::create( UIMachineWindow *pMachineWindow 534 , VBoxDefs::RenderMode renderMode 702 535 #ifdef VBOX_WITH_VIDEOHWACCEL 703 bool accelerate2DVideo, 704 #endif 705 QWidget *parent) 706 : QAbstractScrollArea (parent) 707 , mMainWnd (mainWnd) 708 , mConsole (console) 709 , gs (vboxGlobal().settings()) 710 , mAttached (false) 711 , mKbdCaptured (false) 712 , mMouseCaptured (false) 713 , mMouseAbsolute (false) 714 , mMouseIntegration (true) 715 , m_iLastMouseWheelDelta(0) 716 , mDisableAutoCapture (false) 717 , mIsHostkeyPressed (false) 718 , mIsHostkeyAlone (false) 719 , mIgnoreMainwndResize (true) 720 , mAutoresizeGuest (false) 721 , mIgnoreFrameBufferResize (false) 722 , mIgnoreGuestResize (false) 723 , mDoResize (false) 724 , mGuestSupportsGraphics (false) 725 , mNumLock (false) 726 , mScrollLock (false) 727 , mCapsLock (false) 728 , muNumLockAdaptionCnt (2) 729 , muCapsLockAdaptionCnt (2) 730 , mode (rm) 536 , bool bAccelerate2DVideo 537 #endif 538 , UIVisualStateType visualStateType) 539 { 540 UIMachineView *view = 0; 541 switch (visualStateType) 542 { 543 case UIVisualStateType_Normal: 544 view = new UIMachineViewNormal( pMachineWindow 545 , renderMode 731 546 #ifdef VBOX_WITH_VIDEOHWACCEL 732 , mAccelerate2DVideo(accelerate2DVideo) 733 #endif 734 #if defined(Q_WS_WIN) 735 , mAlphaCursor (NULL) 736 #endif 737 #if defined(Q_WS_MAC) 738 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA) 739 , mDarwinEventHandlerRef (NULL) 740 # endif 741 , mDarwinKeyModifiers (0) 742 , mKeyboardGrabbed (false) 743 , mDockIconEnabled (true) 744 #endif 745 , mDesktopGeo (DesktopGeo_Invalid) 746 , mPassCAD (false) 747 /* Don't show a hardware pointer until we have one to show */ 748 , mHideHostPointer (true) 749 { 750 Assert (!mConsole.isNull() && 751 !mConsole.GetDisplay().isNull() && 752 !mConsole.GetKeyboard().isNull() && 753 !mConsole.GetMouse().isNull()); 754 755 #ifdef Q_WS_MAC 756 /* Overlay logo for the dock icon */ 757 //mVirtualBoxLogo = ::darwinToCGImageRef ("VirtualBox_cube_42px.png"); 758 QString osTypeId = mConsole.GetGuest().GetOSTypeId(); 759 mDockIconPreview = new VBoxDockIconPreview (mMainWnd, vboxGlobal().vmGuestOSTypeIcon (osTypeId)); 760 761 # ifdef QT_MAC_USE_COCOA 762 /** @todo Carbon -> Cocoa */ 763 # else /* !QT_MAC_USE_COCOA */ 764 /* Install the event handler which will proceed external window handling */ 765 EventHandlerUPP eventHandler = ::NewEventHandlerUPP (::darwinOverlayWindowHandler); 766 EventTypeSpec eventTypes[] = 767 { 768 { kEventClassVBox, kEventVBoxShowWindow }, 769 { kEventClassVBox, kEventVBoxHideWindow }, 770 { kEventClassVBox, kEventVBoxMoveWindow }, 771 { kEventClassVBox, kEventVBoxResizeWindow }, 772 { kEventClassVBox, kEventVBoxDisposeWindow }, 773 { kEventClassVBox, kEventVBoxUpdateDock } 774 }; 775 776 mDarwinWindowOverlayHandlerRef = NULL; 777 ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 778 this, &mDarwinWindowOverlayHandlerRef); 779 ::DisposeEventHandlerUPP (eventHandler); 780 # endif /* !QT_MAC_USE_COCOA */ 781 #endif /* QT_WS_MAC */ 782 783 /* No frame around the view */ 784 setFrameStyle (QFrame::NoFrame); 785 786 #ifdef VBOX_GUI_USE_QGL 787 QWidget *pViewport; 788 switch (mode) 789 { 790 case VBoxDefs::QGLMode: 791 pViewport = new VBoxGLWidget (this, this, NULL); 547 , bAccelerate2DVideo 548 #endif 549 ); 550 break; 551 case UIVisualStateType_Fullscreen: 552 view = new UIMachineViewNormal( pMachineWindow 553 , renderMode 554 #ifdef VBOX_WITH_VIDEOHWACCEL 555 , bAccelerate2DVideo 556 #endif 557 ); 558 break; 559 case UIVisualStateType_Seamless: 560 view = new UIMachineViewNormal( pMachineWindow 561 , renderMode 562 #ifdef VBOX_WITH_VIDEOHWACCEL 563 , bAccelerate2DVideo 564 #endif 565 ); 792 566 break; 793 567 default: 794 pViewport = new VBoxViewport (this);795 }796 #else797 VBoxViewport *pViewport = new VBoxViewport (this);798 #endif799 setViewport (pViewport);800 // pViewport->vboxDoInit();801 802 /* enable MouseMove events */803 viewport()->setMouseTracking (true);804 805 /*806 * QScrollView does the below on its own, but let's do it anyway807 * for the case it will not do it in the future.808 */809 viewport()->installEventFilter (this);810 811 /* to fix some focus issues */812 mMainWnd->menuBar()->installEventFilter (this);813 814 /* we want to be notified on some parent's events */815 mMainWnd->installEventFilter (this);816 817 #ifdef Q_WS_X11818 /* initialize the X keyboard subsystem */819 initMappedX11Keyboard(QX11Info::display(),820 vboxGlobal().settings().publicProperty ("GUI/RemapScancodes"));821 #endif822 823 ::memset (mPressedKeys, 0, sizeof (mPressedKeys));824 825 /* setup rendering */826 827 CDisplay display = mConsole.GetDisplay();828 Assert (!display.isNull());829 830 mFrameBuf = NULL;831 832 LogFlowFunc (("Rendering mode: %d\n", mode));833 834 switch (mode)835 {836 #if defined (VBOX_GUI_USE_QGL)837 case VBoxDefs::QGLMode:838 mFrameBuf = new VBoxQGLFrameBuffer (this);839 568 break; 840 // case VBoxDefs::QGLOverlayMode: 841 // mFrameBuf = new VBoxQGLOverlayFrameBuffer (this); 842 // break; 843 #endif 844 #if defined (VBOX_GUI_USE_QIMAGE) 845 case VBoxDefs::QImageMode: 846 mFrameBuf = 847 #ifdef VBOX_WITH_VIDEOHWACCEL 848 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQImageFrameBuffer> (this, &mainWnd->session()) : 849 #endif 850 new VBoxQImageFrameBuffer (this); 569 } 570 return view; 571 } 572 573 void UIMachineView::onViewOpened() 574 { 575 /* Variable m_bIsMachineWindowResizeIgnored was initially "true" to ignore QT 576 * initial resize event in case of auto-resize feature is on. 577 * Currently, initial resize event is already processed, so we set 578 * m_bIsMachineWindowResizeIgnored to "false" to process all further resize 579 * events as user-initiated window resize events. */ 580 m_bIsMachineWindowResizeIgnored = false; 581 } 582 583 int UIMachineView::contentsX() const 584 { 585 return horizontalScrollBar()->value(); 586 } 587 588 int UIMachineView::contentsY() const 589 { 590 return verticalScrollBar()->value(); 591 } 592 593 QRect UIMachineView::desktopGeometry() const 594 { 595 QRect rc; 596 switch (mDesktopGeo) 597 { 598 case DesktopGeo_Fixed: 599 case DesktopGeo_Automatic: 600 rc = QRect(0, 0, 601 qMax(mDesktopGeometry.width(), mStoredConsoleSize.width()), 602 qMax(mDesktopGeometry.height(), mStoredConsoleSize.height())); 851 603 break; 852 #endif 853 #if defined (VBOX_GUI_USE_SDL) 854 case VBoxDefs::SDLMode: 855 /* Indicate that we are doing all 856 * drawing stuff ourself */ 857 pViewport->setAttribute (Qt::WA_PaintOnScreen); 858 # ifdef Q_WS_X11 859 /* This is somehow necessary to prevent strange X11 warnings on 860 * i386 and segfaults on x86_64. */ 861 XFlush(QX11Info::display()); 862 # endif 863 mFrameBuf = 864 #if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */ 865 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxSDLFrameBuffer> (this, &mainWnd->session()) : 866 #endif 867 new VBoxSDLFrameBuffer (this); 868 /* 869 * disable scrollbars because we cannot correctly draw in a 870 * scrolled window using SDL 871 */ 872 horizontalScrollBar()->setEnabled (false); 873 verticalScrollBar()->setEnabled (false); 604 case DesktopGeo_Any: 605 rc = QRect(0, 0, 0, 0); 874 606 break; 875 #endif876 #if defined (VBOX_GUI_USE_DDRAW)877 case VBoxDefs::DDRAWMode:878 mFrameBuf = new VBoxDDRAWFrameBuffer (this);879 break;880 #endif881 #if defined (VBOX_GUI_USE_QUARTZ2D)882 case VBoxDefs::Quartz2DMode:883 /* Indicate that we are doing all884 * drawing stuff ourself */885 pViewport->setAttribute (Qt::WA_PaintOnScreen);886 mFrameBuf =887 #ifdef VBOX_WITH_VIDEOHWACCEL888 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer> (this, &mainWnd->session()) :889 #endif890 new VBoxQuartz2DFrameBuffer (this);891 break;892 #endif893 607 default: 894 AssertReleaseMsgFailed (("Render mode must be valid: %d\n", mode)); 895 LogRel (("Invalid render mode: %d\n", mode)); 896 qApp->exit (1); 897 break; 898 } 899 900 #if defined (VBOX_GUI_USE_DDRAW) 901 if (!mFrameBuf || mFrameBuf->address() == NULL) 902 { 903 if (mFrameBuf) 904 delete mFrameBuf; 905 mode = VBoxDefs::QImageMode; 906 mFrameBuf = new VBoxQImageFrameBuffer (this); 907 } 908 #endif 909 910 if (mFrameBuf) 911 { 912 mFrameBuf->AddRef(); 913 display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer (mFrameBuf)); 914 } 915 916 /* setup the callback */ 917 mCallback = CConsoleCallback (new VBoxConsoleCallback (this)); 918 mConsole.RegisterCallback (mCallback); 919 AssertWrapperOk (mConsole); 920 921 QPalette palette (viewport()->palette()); 922 palette.setColor (viewport()->backgroundRole(), Qt::black); 923 viewport()->setPalette (palette); 924 925 setSizePolicy (QSizePolicy (QSizePolicy::Maximum, QSizePolicy::Maximum)); 926 setMaximumSize (sizeHint()); 927 928 setFocusPolicy (Qt::WheelFocus); 929 930 /* Remember the desktop geometry and register for geometry change 931 events for telling the guest about video modes we like. */ 932 933 QString desktopGeometry = vboxGlobal().settings() 934 .publicProperty ("GUI/MaxGuestResolution"); 935 if ((desktopGeometry == QString::null) || 936 (desktopGeometry == "auto")) 937 setDesktopGeometry (DesktopGeo_Automatic, 0, 0); 938 else if (desktopGeometry == "any") 939 setDesktopGeometry (DesktopGeo_Any, 0, 0); 940 else 941 { 942 int width = desktopGeometry.section (',', 0, 0).toInt(); 943 int height = desktopGeometry.section (',', 1, 1).toInt(); 944 setDesktopGeometry (DesktopGeo_Fixed, width, height); 945 } 946 connect (QApplication::desktop(), SIGNAL (resized (int)), 947 this, SLOT (doResizeDesktop (int))); 948 949 QString passCAD = mConsole.GetMachine().GetExtraData (VBoxDefs::GUI_PassCAD); 950 if (!passCAD.isEmpty() && 951 ((passCAD != "false") || (passCAD != "no")) 952 ) 953 mPassCAD = true; 954 955 #if defined (Q_WS_WIN) 956 gView = this; 957 #endif 958 959 #if defined (Q_WS_PM) 960 bool ok = VBoxHlpInstallKbdHook (0, winId(), UM_PREACCEL_CHAR); 961 Assert (ok); 962 NOREF (ok); 963 #endif 964 } 965 966 VBoxConsoleView::~VBoxConsoleView() 967 { 968 #if defined (Q_WS_PM) 969 bool ok = VBoxHlpUninstallKbdHook (0, winId(), UM_PREACCEL_CHAR); 970 Assert (ok); 971 NOREF (ok); 972 #endif 973 974 #if defined (Q_WS_WIN) 975 if (gKbdHook) 976 UnhookWindowsHookEx (gKbdHook); 977 gView = 0; 978 if (mAlphaCursor) 979 DestroyIcon (mAlphaCursor); 980 #endif 981 982 if (mFrameBuf) 983 { 984 /* detach our framebuffer from Display */ 985 CDisplay display = mConsole.GetDisplay(); 986 Assert (!display.isNull()); 987 display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL)); 988 /* release the reference */ 989 mFrameBuf->Release(); 990 mFrameBuf = NULL; 991 } 992 993 mConsole.UnregisterCallback (mCallback); 994 995 #if defined (Q_WS_MAC) 996 # if !defined (QT_MAC_USE_COCOA) 997 if (mDarwinWindowOverlayHandlerRef) 998 { 999 ::RemoveEventHandler (mDarwinWindowOverlayHandlerRef); 1000 mDarwinWindowOverlayHandlerRef = NULL; 1001 } 1002 # endif 1003 delete mDockIconPreview; 1004 mDockIconPreview = NULL; 1005 #endif 1006 } 1007 1008 // 1009 // Public members 1010 ///////////////////////////////////////////////////////////////////////////// 1011 1012 QSize VBoxConsoleView::sizeHint() const 1013 { 1014 #ifdef VBOX_WITH_DEBUGGER /** @todo figure out a more proper fix. */ 1015 /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done 1016 * by DevVGA if provoked before power on. */ 1017 QSize fb(mFrameBuf->width(), mFrameBuf->height()); 1018 if ( ( fb.width() < 16 1019 || fb.height() < 16) 1020 && ( vboxGlobal().isStartPausedEnabled() 1021 || vboxGlobal().isDebuggerAutoShowEnabled()) ) 1022 fb = QSize(640, 480); 1023 return QSize (fb.width() + frameWidth() * 2, 1024 fb.height() + frameWidth() * 2); 1025 #else 1026 return QSize (mFrameBuf->width() + frameWidth() * 2, 1027 mFrameBuf->height() + frameWidth() * 2); 1028 #endif 1029 } 1030 1031 /** 1032 * Attaches this console view to the managed virtual machine. 1033 * 1034 * @note This method is not really necessary these days -- the only place where 1035 * it gets called is VBoxConsole::openView(), right after powering the 1036 * VM up. We leave it as is just in case attaching/detaching will become 1037 * necessary some day (there are useful attached checks everywhere in the 1038 * code). 1039 */ 1040 void VBoxConsoleView::attach() 1041 { 1042 if (!mAttached) 1043 { 1044 mAttached = true; 1045 } 1046 } 1047 1048 /** 1049 * Detaches this console view from the VM. Must be called to indicate 1050 * that the virtual machine managed by this instance will be no more valid 1051 * after this call. 1052 * 1053 * @note This method is not really necessary these days -- the only place where 1054 * it gets called is VBoxConsole::closeView(), when the VM is powered 1055 * down, before deleting VBoxConsoleView. We leave it as is just in case 1056 * attaching/detaching will become necessary some day (there are useful 1057 * attached checks everywhere in the code). 1058 */ 1059 void VBoxConsoleView::detach() 1060 { 1061 if (mAttached) 1062 { 1063 /* reuse the focus event handler to uncapture everything */ 1064 focusEvent (false); 1065 mAttached = false; 1066 } 1067 } 1068 1069 /** 1070 * Resizes the toplevel widget to fit the console view w/o scrollbars. 1071 * If adjustPosition is true and such resize is not possible (because the 1072 * console view size is lagrer then the available screen space) the toplevel 1073 * widget is resized and moved to become as large as possible while staying 1074 * fully visible. 1075 */ 1076 void VBoxConsoleView::normalizeGeometry (bool adjustPosition /* = false */) 1077 { 1078 /* Make no normalizeGeometry in case we are in manual resize 1079 * mode or main window is maximized */ 1080 if (mMainWnd->isWindowMaximized() || mMainWnd->isWindowFullScreen()) 608 AssertMsgFailed(("Bad geometry type %d\n", mDesktopGeo)); 609 } 610 return rc; 611 } 612 613 void UIMachineView::setIgnoreGuestResize(bool bIgnore) 614 { 615 m_bIsGuestResizeIgnored = bIgnore; 616 } 617 618 void UIMachineView::setMouseIntegrationEnabled(bool bEnabled) 619 { 620 if (m_bIsMouseIntegrated == bEnabled) 1081 621 return; 1082 622 1083 QWidget *tlw = window(); 1084 1085 /* calculate client window offsets */ 1086 QRect fr = tlw->frameGeometry(); 1087 QRect r = tlw->geometry(); 1088 int dl = r.left() - fr.left(); 1089 int dt = r.top() - fr.top(); 1090 int dr = fr.right() - r.right(); 1091 int db = fr.bottom() - r.bottom(); 1092 1093 /* get the best size w/o scroll bars */ 1094 QSize s = tlw->sizeHint(); 1095 1096 /* resize the frame to fit the contents */ 1097 s -= tlw->size(); 1098 fr.setRight (fr.right() + s.width()); 1099 fr.setBottom (fr.bottom() + s.height()); 1100 1101 if (adjustPosition) 1102 { 1103 QRegion ar; 1104 QDesktopWidget *dwt = QApplication::desktop(); 1105 if (dwt->isVirtualDesktop()) 1106 /* Compose complex available region */ 1107 for (int i = 0; i < dwt->numScreens(); ++ i) 1108 ar += dwt->availableGeometry (i); 1109 else 1110 /* Get just a simple available rectangle */ 1111 ar = dwt->availableGeometry (tlw->pos()); 1112 1113 fr = VBoxGlobal::normalizeGeometry ( 1114 fr, ar, mode != VBoxDefs::SDLMode /* canResize */); 1115 } 1116 1117 #if 0 1118 /* center the frame on the desktop */ 1119 fr.moveCenter (ar.center()); 1120 #endif 1121 1122 /* finally, set the frame geometry */ 1123 tlw->setGeometry (fr.left() + dl, fr.top() + dt, 1124 fr.width() - dl - dr, fr.height() - dt - db); 1125 } 1126 1127 /** 1128 * Pauses or resumes the VM execution. 1129 */ 1130 bool VBoxConsoleView::pause (bool on) 1131 { 1132 /* QAction::setOn() emits the toggled() signal, so avoid recursion when 1133 * QAction::setOn() is called from VBoxConsoleWnd::updateMachineState() */ 1134 if (isPaused() == on) 1135 return true; 1136 1137 if (on) 1138 mConsole.Pause(); 1139 else 1140 mConsole.Resume(); 1141 1142 bool ok = mConsole.isOk(); 1143 if (!ok) 1144 { 1145 if (on) 1146 vboxProblem().cannotPauseMachine (mConsole); 1147 else 1148 vboxProblem().cannotResumeMachine (mConsole); 1149 } 1150 1151 return ok; 1152 } 1153 1154 /** 1155 * Temporarily disables the mouse integration (or enables it back). 1156 */ 1157 void VBoxConsoleView::setMouseIntegrationEnabled (bool enabled) 1158 { 1159 if (mMouseIntegration == enabled) 1160 return; 1161 1162 if (mMouseAbsolute) 1163 captureMouse (!enabled, false); 623 if (m_bIsMouseAbsolute) 624 captureMouse(!bEnabled, false); 1164 625 1165 626 /* Hiding host cursor in case we are entering mouse integration … … 1178 639 * This notification is not always possible though, as not all guests 1179 640 * support switching to a hardware pointer on demand. */ 1180 if ( enabled)1181 viewport()->setCursor (QCursor(Qt::BlankCursor));1182 1183 m MouseIntegration = enabled;641 if (bEnabled) 642 viewport()->setCursor(QCursor(Qt::BlankCursor)); 643 644 m_bIsMouseIntegrated = bEnabled; 1184 645 1185 646 emitMouseStateChanged(); 1186 647 } 1187 648 1188 void VBoxConsoleView::setAutoresizeGuest (bool on) 1189 { 1190 if (mAutoresizeGuest != on) 1191 { 1192 mAutoresizeGuest = on; 1193 1194 maybeRestrictMinimumSize(); 1195 1196 if (mGuestSupportsGraphics && mAutoresizeGuest) 1197 doResizeHint(); 1198 } 1199 } 1200 1201 /** 1202 * This method is called by VBoxConsoleWnd after it does everything necessary 1203 * on its side to go to or from fullscreen, but before it is shown. 1204 */ 1205 void VBoxConsoleView::onFullscreenChange (bool /* on */) 1206 { 1207 /* Nothing to do here so far */ 1208 } 1209 1210 /** 1211 * Notify the console scroll-view about the console-window is opened. 1212 */ 1213 void VBoxConsoleView::onViewOpened() 1214 { 1215 /* Variable mIgnoreMainwndResize was initially "true" to ignore QT 1216 * initial resize event in case of auto-resize feature is on. 1217 * Currently, initial resize event is already processed, so we set 1218 * mIgnoreMainwndResize to "false" to process all further resize 1219 * events as user-initiated window resize events. */ 1220 mIgnoreMainwndResize = false; 1221 } 1222 1223 // 1224 // Protected Events 1225 ///////////////////////////////////////////////////////////////////////////// 1226 1227 bool VBoxConsoleView::event (QEvent *e) 1228 { 1229 if (mAttached) 649 UIMachineView::UIMachineView( UIMachineWindow *pMachineWindow 650 , VBoxDefs::RenderMode renderMode 651 #ifdef VBOX_WITH_VIDEOHWACCEL 652 , bool bAccelerate2DVideo 653 #endif 654 ) 655 : QAbstractScrollArea(pMachineWindow->machineWindow()) 656 /* Protected members: */ 657 , mode(renderMode) 658 , m_bIsGuestSupportsGraphics(false) 659 /* Private members: */ 660 , m_pMachineWindow(pMachineWindow) 661 , m_console(pMachineWindow->machineLogic()->session().GetConsole()) 662 , m_globalSettings(vboxGlobal().settings()) 663 , m_iLastMouseWheelDelta(0) 664 , muNumLockAdaptionCnt(2) 665 , muCapsLockAdaptionCnt(2) 666 , m_bIsAutoCaptureDisabled(false) 667 , m_bIsKeyboardCaptured(false) 668 , m_bIsMouseCaptured(false) 669 , m_bIsMouseAbsolute(false) 670 , m_bIsMouseIntegrated(true) 671 , m_bIsHostkeyPressed(false) 672 , m_bIsHostkeyAlone (false) 673 , m_bIsMachineWindowResizeIgnored(true) 674 , m_bIsFrameBufferResizeIgnored(false) 675 , m_bIsGuestResizeIgnored(false) 676 , mDoResize(false) 677 , mNumLock(false) 678 , mScrollLock(false) 679 , mCapsLock(false) 680 #ifdef VBOX_WITH_VIDEOHWACCEL 681 , mAccelerate2DVideo(bAccelerate2DVideo) 682 #endif 683 #if defined(Q_WS_WIN) 684 , mAlphaCursor (NULL) 685 #endif 686 #if defined(Q_WS_MAC) 687 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA) 688 , mDarwinEventHandlerRef (NULL) 689 # endif 690 , mDarwinKeyModifiers (0) 691 , mKeyboardGrabbed (false) 692 , mDockIconEnabled (true) 693 #endif 694 , mDesktopGeo (DesktopGeo_Invalid) 695 , mPassCAD (false) 696 /* Don't show a hardware pointer until we have one to show */ 697 , mHideHostPointer (true) 698 { 699 Assert (!m_console.isNull() && !m_console.GetDisplay().isNull() && !m_console.GetKeyboard().isNull() && !m_console.GetMouse().isNull()); 700 701 #ifdef Q_WS_MAC 702 /* Overlay logo for the dock icon */ 703 //mVirtualBoxLogo = ::darwinToCGImageRef("VirtualBox_cube_42px.png"); 704 QString osTypeId = m_console.GetGuest().GetOSTypeId(); 705 mDockIconPreview = new VBoxDockIconPreview(machineWindowWrapper(), vboxGlobal().vmGuestOSTypeIcon (osTypeId)); 706 707 # ifdef QT_MAC_USE_COCOA 708 /** @todo Carbon -> Cocoa */ 709 # else /* !QT_MAC_USE_COCOA */ 710 /* Install the event handler which will proceed external window handling */ 711 EventHandlerUPP eventHandler = ::NewEventHandlerUPP(::darwinOverlayWindowHandler); 712 EventTypeSpec eventTypes[] = 713 { 714 { kEventClassVBox, kEventVBoxShowWindow }, 715 { kEventClassVBox, kEventVBoxHideWindow }, 716 { kEventClassVBox, kEventVBoxMoveWindow }, 717 { kEventClassVBox, kEventVBoxResizeWindow }, 718 { kEventClassVBox, kEventVBoxDisposeWindow }, 719 { kEventClassVBox, kEventVBoxUpdateDock } 720 }; 721 722 mDarwinWindowOverlayHandlerRef = NULL; 723 ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], this, &mDarwinWindowOverlayHandlerRef); 724 ::DisposeEventHandlerUPP(eventHandler); 725 # endif /* !QT_MAC_USE_COCOA */ 726 #endif /* QT_WS_MAC */ 727 728 /* No frame around the view */ 729 setFrameStyle(QFrame::NoFrame); 730 731 #ifdef VBOX_GUI_USE_QGL 732 QWidget *pViewport; 733 switch (mode) 734 { 735 // TODO: Fix that! 736 //case VBoxDefs::QGLMode: 737 // pViewport = new VBoxGLWidget(this, this, NULL); 738 // break; 739 default: 740 pViewport = new VBoxViewport(this); 741 } 742 #else 743 VBoxViewport *pViewport = new VBoxViewport(this); 744 #endif 745 setViewport(pViewport); 746 // pViewport->vboxDoInit(); 747 748 /* enable MouseMove events */ 749 viewport()->setMouseTracking(true); 750 751 /* 752 * QScrollView does the below on its own, but let's do it anyway 753 * for the case it will not do it in the future. 754 */ 755 viewport()->installEventFilter(this); 756 757 /* to fix some focus issues */ 758 // TODO: Fix that! 759 //machineWindowWrapper()->menuBar()->installEventFilter(this); 760 761 /* we want to be notified on some parent's events */ 762 machineWindowWrapper()->machineWindow()->installEventFilter(this); 763 764 #ifdef Q_WS_X11 765 /* initialize the X keyboard subsystem */ 766 initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes")); 767 #endif 768 769 ::memset(mPressedKeys, 0, sizeof(mPressedKeys)); 770 771 /* setup rendering */ 772 773 CDisplay display = m_console.GetDisplay(); 774 Assert(!display.isNull()); 775 776 mFrameBuf = NULL; 777 778 LogFlowFunc(("Rendering mode: %d\n", mode)); 779 780 switch (mode) 781 { 782 #if defined (VBOX_GUI_USE_QGL) 783 // TODO: Fix that! 784 // case VBoxDefs::QGLMode: 785 // mFrameBuf = new VBoxQGLFrameBuffer(this); 786 // break; 787 // case VBoxDefs::QGLOverlayMode: 788 // mFrameBuf = new VBoxQGLOverlayFrameBuffer(this); 789 // break; 790 #endif 791 #if defined (VBOX_GUI_USE_QIMAGE) 792 case VBoxDefs::QImageMode: 793 mFrameBuf = 794 #ifdef VBOX_WITH_VIDEOHWACCEL 795 // mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UIFrameBufferQImage>(this, &machineWindowWrapper()->session()) : 796 #endif 797 new UIFrameBufferQImage(this); 798 break; 799 #endif 800 #if defined (VBOX_GUI_USE_SDL) 801 case VBoxDefs::SDLMode: 802 /* Indicate that we are doing all 803 * drawing stuff ourself */ 804 pViewport->setAttribute(Qt::WA_PaintOnScreen); 805 # ifdef Q_WS_X11 806 /* This is somehow necessary to prevent strange X11 warnings on 807 * i386 and segfaults on x86_64. */ 808 XFlush(QX11Info::display()); 809 # endif 810 // mFrameBuf = 811 #if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */ 812 // mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxSDLFrameBuffer> (this, &machineWindowWrapper()->session()) : 813 #endif 814 // new VBoxSDLFrameBuffer(this); 815 /* 816 * disable scrollbars because we cannot correctly draw in a 817 * scrolled window using SDL 818 */ 819 horizontalScrollBar()->setEnabled(false); 820 verticalScrollBar()->setEnabled(false); 821 break; 822 #endif 823 #if defined (VBOX_GUI_USE_DDRAW) 824 case VBoxDefs::DDRAWMode: 825 mFrameBuf = new VBoxDDRAWFrameBuffer(this); 826 break; 827 #endif 828 #if defined (VBOX_GUI_USE_QUARTZ2D) 829 case VBoxDefs::Quartz2DMode: 830 /* Indicate that we are doing all 831 * drawing stuff ourself */ 832 pViewport->setAttribute(Qt::WA_PaintOnScreen); 833 mFrameBuf = 834 #ifdef VBOX_WITH_VIDEOHWACCEL 835 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer>(this, &machineWindowWrapper()->session()) : 836 #endif 837 new VBoxQuartz2DFrameBuffer(this); 838 break; 839 #endif 840 default: 841 AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode)); 842 LogRel (("Invalid render mode: %d\n", mode)); 843 qApp->exit (1); 844 break; 845 } 846 847 #if defined (VBOX_GUI_USE_DDRAW) 848 if (!mFrameBuf || mFrameBuf->address() == NULL) 849 { 850 if (mFrameBuf) 851 delete mFrameBuf; 852 mode = VBoxDefs::QImageMode; 853 mFrameBuf = new UIFrameBufferQImage(this); 854 } 855 #endif 856 857 if (mFrameBuf) 858 { 859 mFrameBuf->AddRef(); 860 display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(mFrameBuf)); 861 } 862 863 /* setup the callback */ 864 mCallback = CConsoleCallback(new UIConsoleCallback(this)); 865 m_console.RegisterCallback(mCallback); 866 AssertWrapperOk(m_console); 867 868 QPalette palette(viewport()->palette()); 869 palette.setColor(viewport()->backgroundRole(), Qt::black); 870 viewport()->setPalette(palette); 871 872 setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum)); 873 setMaximumSize(sizeHint()); 874 875 setFocusPolicy(Qt::WheelFocus); 876 877 /* Remember the desktop geometry and register for geometry change 878 events for telling the guest about video modes we like. */ 879 880 QString desktopGeometry = vboxGlobal().settings().publicProperty("GUI/MaxGuestResolution"); 881 if ((desktopGeometry == QString::null) || (desktopGeometry == "auto")) 882 setDesktopGeometry(DesktopGeo_Automatic, 0, 0); 883 else if (desktopGeometry == "any") 884 setDesktopGeometry(DesktopGeo_Any, 0, 0); 885 else 886 { 887 int width = desktopGeometry.section(',', 0, 0).toInt(); 888 int height = desktopGeometry.section(',', 1, 1).toInt(); 889 setDesktopGeometry(DesktopGeo_Fixed, width, height); 890 } 891 connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(doResizeDesktop(int))); 892 893 QString passCAD = m_console.GetMachine().GetExtraData(VBoxDefs::GUI_PassCAD); 894 if (!passCAD.isEmpty() && ((passCAD != "false") || (passCAD != "no"))) 895 mPassCAD = true; 896 897 #if defined (Q_WS_WIN) 898 gView = this; 899 #endif 900 901 #if defined (Q_WS_PM) 902 bool ok = VBoxHlpInstallKbdHook(0, winId(), UM_PREACCEL_CHAR); 903 Assert (ok); 904 NOREF (ok); 905 #endif 906 907 #ifdef Q_WS_MAC 908 /* Dock icon update connection */ 909 connect(&vboxGlobal(), SIGNAL(dockIconUpdateChanged(const VBoxChangeDockIconUpdateEvent &)), 910 this, SLOT(sltChangeDockIconUpdate(const VBoxChangeDockIconUpdateEvent &))); 911 /* Presentation Mode connection */ 912 connect(&vboxGlobal(), SIGNAL(presentationModeChanged(const VBoxChangePresentationModeEvent &)), 913 this, SLOT(sltChangePresentationMode(const VBoxChangePresentationModeEvent &))); 914 #endif 915 } 916 917 UIMachineView::~UIMachineView() 918 { 919 #if 0 920 #if defined (Q_WS_PM) 921 bool ok = VBoxHlpUninstallKbdHook(0, winId(), UM_PREACCEL_CHAR); 922 Assert (ok); 923 NOREF (ok); 924 #endif 925 926 #if defined (Q_WS_WIN) 927 if (gKbdHook) 928 UnhookWindowsHookEx(gKbdHook); 929 gView = 0; 930 if (mAlphaCursor) 931 DestroyIcon(mAlphaCursor); 932 #endif 933 934 if (mFrameBuf) 935 { 936 /* detach our framebuffer from Display */ 937 CDisplay display = m_console.GetDisplay(); 938 Assert(!display.isNull()); 939 display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL)); 940 /* release the reference */ 941 mFrameBuf->Release(); 942 mFrameBuf = NULL; 943 } 944 945 m_console.UnregisterCallback(mCallback); 946 947 #if defined (Q_WS_MAC) 948 # if !defined (QT_MAC_USE_COCOA) 949 if (mDarwinWindowOverlayHandlerRef) 950 { 951 ::RemoveEventHandler(mDarwinWindowOverlayHandlerRef); 952 mDarwinWindowOverlayHandlerRef = NULL; 953 } 954 # endif 955 delete mDockIconPreview; 956 mDockIconPreview = NULL; 957 #endif 958 #endif 959 } 960 961 void UIMachineView::calculateDesktopGeometry() 962 { 963 /* This method should not get called until we have initially set up the */ 964 Assert((mDesktopGeo != DesktopGeo_Invalid)); 965 /* If we are not doing automatic geometry calculation then there is nothing to do. */ 966 if (DesktopGeo_Automatic == mDesktopGeo) 967 { 968 /* Available geometry of the desktop. If the desktop is a single 969 * screen, this will exclude space taken up by desktop taskbars 970 * and things, but this is unfortunately not true for the more 971 * complex case of a desktop spanning multiple screens. */ 972 QRect desktop = availableGeometry(); 973 /* The area taken up by the console window on the desktop, 974 * including window frame, title and menu bar and whatnot. */ 975 QRect frame = machineWindowWrapper()->machineWindow()->frameGeometry(); 976 /* The area taken up by the console window, minus all decorations. */ 977 //QRect window = machineWindowWrapper()->centralWidget()->geometry(); // TODO check that! 978 /* To work out how big we can make the console window while still 979 * fitting on the desktop, we calculate desktop - frame + window. 980 * This works because the difference between frame and window 981 * (or at least its width and height) is a constant. */ 982 //mDesktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(), 983 // desktop.height() - frame.height() + window.height()); 984 } 985 } 986 987 QSize UIMachineView::sizeHint() const 988 { 989 #ifdef VBOX_WITH_DEBUGGER 990 /** @todo figure out a more proper fix. */ 991 /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done 992 * by DevVGA if provoked before power on. */ 993 QSize fb(mFrameBuf->width(), mFrameBuf->height()); 994 if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled())) 995 fb = QSize(640, 480); 996 return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2); 997 #else 998 return QSize(mFrameBuf->width() + frameWidth() * 2, mFrameBuf->height() + frameWidth() * 2); 999 #endif 1000 } 1001 1002 #ifdef Q_WS_MAC 1003 void UIMachineLogic::sltChangeDockIconUpdate(const VBoxChangeDockIconUpdateEvent &event) 1004 { 1005 setDockIconEnabled(event.mChanged); 1006 updateDockOverlay(); 1007 } 1008 1009 # ifdef QT_MAC_USE_COCOA 1010 void UIMachineLogic::sltChangePresentationMode(const VBoxChangePresentationModeEvent &event) 1011 { 1012 if (mIsFullscreen) 1013 { 1014 /* First check if we are on the primary screen, only than the presentation mode have to be changed. */ 1015 QDesktopWidget* pDesktop = QApplication::desktop(); 1016 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 1017 { 1018 QString testStr = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_PresentationModeEnabled).toLower(); 1019 /* Default to false if it is an empty value */ 1020 if (testStr.isEmpty() || testStr == "false") 1021 SetSystemUIMode(kUIModeAllHidden, 0); 1022 else 1023 SetSystemUIMode(kUIModeAllSuppressed, 0); 1024 } 1025 } 1026 else 1027 SetSystemUIMode(kUIModeNormal, 0); 1028 } 1029 # endif /* QT_MAC_USE_COCOA */ 1030 #endif 1031 1032 int UIMachineView::contentsWidth() const 1033 { 1034 return mFrameBuf->width(); 1035 } 1036 1037 int UIMachineView::contentsHeight() const 1038 { 1039 return mFrameBuf->height(); 1040 } 1041 1042 int UIMachineView::visibleWidth() const 1043 { 1044 return horizontalScrollBar()->pageStep(); 1045 } 1046 1047 int UIMachineView::visibleHeight() const 1048 { 1049 return verticalScrollBar()->pageStep(); 1050 } 1051 1052 bool UIMachineView::event(QEvent *e) 1053 { 1054 //if (m_bIsAttached) 1230 1055 { 1231 1056 switch (e->type()) … … 1259 1084 * to be ignored at all, leaving previous framebuffer, 1260 1085 * console widget and vm window size preserved. */ 1261 if (m IgnoreGuestResize)1086 if (m_bIsGuestResizeIgnored) 1262 1087 return true; 1263 1088 1264 bool oldIgnoreMainwndResize = m IgnoreMainwndResize;1265 m IgnoreMainwndResize= true;1266 1267 VBoxResizeEvent *re = (VBoxResizeEvent *) e;1089 bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored; 1090 m_bIsMachineWindowResizeIgnored = true; 1091 1092 UIResizeEvent *re = (UIResizeEvent *) e; 1268 1093 LogFlow (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n", 1269 1094 re->width(), re->height(), re->bitsPerPixel())); … … 1306 1131 * So it is necessary to perform updateMouseClipping() for 1307 1132 * the guest resize event if the mouse cursor was captured. */ 1308 if (m MouseCaptured)1133 if (m_bIsMouseCaptured) 1309 1134 updateMouseClipping(); 1310 1135 … … 1315 1140 1316 1141 /* resize the guest canvas */ 1317 if (!m IgnoreFrameBufferResize)1142 if (!m_bIsFrameBufferResizeIgnored) 1318 1143 resize (re->width(), re->height()); 1319 1144 updateSliders(); … … 1330 1155 #endif /* Q_WS_X11 */ 1331 1156 1332 if (!m IgnoreFrameBufferResize)1157 if (!m_bIsFrameBufferResizeIgnored) 1333 1158 normalizeGeometry (true /* adjustPosition */); 1334 1159 1335 1160 /* report to the VM thread that we finished resizing */ 1336 m Console.GetDisplay().ResizeCompleted (0);1337 1338 m IgnoreMainwndResize= oldIgnoreMainwndResize;1161 m_console.GetDisplay().ResizeCompleted (0); 1162 1163 m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize; 1339 1164 1340 1165 /* update geometry after entering fullscreen | seamless */ 1341 if (mMainWnd->isTrueFullscreen() || mMainWnd->isTrueSeamless())1166 // if (machineWindowWrapper()->isTrueFullscreen() || machineWindowWrapper()->isTrueSeamless()) TODO check that! 1342 1167 updateGeometry(); 1343 1168 … … 1354 1179 1355 1180 /* Enable frame-buffer resize watching. */ 1356 if (m IgnoreFrameBufferResize)1181 if (m_bIsFrameBufferResizeIgnored) 1357 1182 { 1358 m IgnoreFrameBufferResize= false;1183 m_bIsFrameBufferResizeIgnored = false; 1359 1184 } 1360 1185 1361 mMainWnd->onDisplayResize (re->width(), re->height());1186 // machineWindowWrapper()->onDisplayResize (re->width(), re->height()); TODO check that! 1362 1187 1363 1188 return true; … … 1367 1192 case VBoxDefs::RepaintEventType: 1368 1193 { 1369 VBoxRepaintEvent *re = (VBoxRepaintEvent *) e;1194 UIRepaintEvent *re = (UIRepaintEvent *) e; 1370 1195 viewport()->repaint (re->x() - contentsX(), 1371 1196 re->y() - contentsY(), 1372 1197 re->width(), re->height()); 1373 /* m Console.GetDisplay().UpdateCompleted(); - the event was acked already */1198 /* m_console.GetDisplay().UpdateCompleted(); - the event was acked already */ 1374 1199 return true; 1375 1200 } … … 1383 1208 #endif 1384 1209 1210 #if 0 1211 // TODO check that! 1385 1212 case VBoxDefs::SetRegionEventType: 1386 1213 { 1387 1214 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e; 1388 if (mMainWnd->isTrueSeamless() && 1389 sre->region() != mLastVisibleRegion) 1215 if (machineWindowWrapper()->isTrueSeamless() && sre->region() != mLastVisibleRegion) 1390 1216 { 1391 1217 mLastVisibleRegion = sre->region(); 1392 m MainWnd->setMask (sre->region());1218 machineWindowWrapper()->setMask (sre->region()); 1393 1219 } 1394 else if (!mLastVisibleRegion.isEmpty() && 1395 !mMainWnd->isTrueSeamless()) 1220 else if (!mLastVisibleRegion.isEmpty() && !machineWindowWrapper()->isTrueSeamless()) 1396 1221 mLastVisibleRegion = QRegion(); 1397 1222 return true; 1398 1223 } 1224 #endif 1399 1225 1400 1226 case VBoxDefs::MousePointerChangeEventType: … … 1404 1230 * supported (change mouse shape type event may arrive after 1405 1231 * mouse capability change that disables integration */ 1406 if (m MouseAbsolute)1232 if (m_bIsMouseAbsolute) 1407 1233 setPointerShape (me); 1408 1234 else … … 1416 1242 { 1417 1243 MouseCapabilityEvent *me = (MouseCapabilityEvent *) e; 1418 if (m MouseAbsolute != me->supportsAbsolute())1244 if (m_bIsMouseAbsolute != me->supportsAbsolute()) 1419 1245 { 1420 m MouseAbsolute = me->supportsAbsolute();1246 m_bIsMouseAbsolute = me->supportsAbsolute(); 1421 1247 /* correct the mouse capture state and reset the cursor 1422 1248 * to the default shape if necessary */ 1423 if (m MouseAbsolute)1249 if (m_bIsMouseAbsolute) 1424 1250 { 1425 CMouse mouse = m Console.GetMouse();1251 CMouse mouse = m_console.GetMouse(); 1426 1252 mouse.PutMouseEventAbsolute (-1, -1, 0, 1427 1253 0 /* Horizontal wheel */, … … 1432 1258 viewport()->unsetCursor(); 1433 1259 emitMouseStateChanged(); 1434 vboxProblem().remindAboutMouseIntegration (m MouseAbsolute);1260 vboxProblem().remindAboutMouseIntegration (m_bIsMouseAbsolute); 1435 1261 } 1436 1262 if (me->needsHostCursor()) 1437 mMainWnd->setMouseIntegrationLocked (false);1263 setMouseIntegrationLocked (false); 1438 1264 else 1439 mMainWnd->setMouseIntegrationLocked (true);1265 setMouseIntegrationLocked (true); 1440 1266 return true; 1441 1267 } … … 1473 1299 * resolution has changed since the VM was last run. */ 1474 1300 #if 0 1475 if (!mDoResize && !m GuestSupportsGraphics &&1301 if (!mDoResize && !m_bIsGuestSupportsGraphics && 1476 1302 ge->supportsGraphics() && 1477 (m MainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen()))1303 (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen())) 1478 1304 mDoResize = true; 1479 1305 #endif 1480 1306 1481 m GuestSupportsGraphics = ge->supportsGraphics();1307 m_bIsGuestSupportsGraphics = ge->supportsGraphics(); 1482 1308 1483 1309 maybeRestrictMinimumSize(); … … 1504 1330 } 1505 1331 1332 #if 0 1506 1333 case VBoxDefs::ActivateMenuEventType: 1507 1334 { … … 1516 1343 */ 1517 1344 QWidgetList list = QApplication::topLevelWidgets(); 1518 bool destroyed = list.indexOf (m MainWnd) < 0;1519 if (!destroyed && m MainWnd->statusBar())1520 m MainWnd->statusBar()->clearMessage();1345 bool destroyed = list.indexOf (machineWindowWrapper()->machineWindow()) < 0; 1346 if (!destroyed && machineWindowWrapper()->machineWindow()->statusBar()) 1347 machineWindowWrapper()->machineWindow()->statusBar()->clearMessage(); 1521 1348 1522 1349 return true; 1523 1350 } 1351 #endif 1524 1352 1525 1353 case VBoxDefs::NetworkAdapterChangeEventType: … … 1547 1375 if (ue->attached()) 1548 1376 vboxProblem().cannotAttachUSBDevice ( 1549 m Console,1377 m_console, 1550 1378 vboxGlobal().details (ue->device()), ue->error()); 1551 1379 else 1552 1380 vboxProblem().cannotDetachUSBDevice ( 1553 m Console,1381 m_console, 1554 1382 vboxGlobal().details (ue->device()), ue->error()); 1555 1383 } … … 1569 1397 { 1570 1398 RuntimeErrorEvent *ee = (RuntimeErrorEvent *) e; 1571 vboxProblem().showRuntimeError (m Console, ee->fatal(),1399 vboxProblem().showRuntimeError (m_console, ee->fatal(), 1572 1400 ee->errorID(), ee->message()); 1573 1401 return true; … … 1585 1413 // impossible to do so using hooks on OS/2). 1586 1414 1587 if (m IsHostkeyPressed)1415 if (m_bIsHostkeyPressed) 1588 1416 { 1589 1417 bool pressed = e->type() == QEvent::KeyPress; 1590 CKeyboard keyboard = m Console.GetKeyboard();1418 CKeyboard keyboard = m_console.GetKeyboard(); 1591 1419 1592 1420 /* whether the host key is Shift so that it will modify 1593 1421 * the hot key values? Note that we don't distinguish 1594 1422 * between left and right shift here (too much hassle) */ 1595 const bool kShift = ( gs.hostKey() == VK_SHIFT ||1596 gs.hostKey() == VK_LSHIFT) &&1423 const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT || 1424 m_globalSettings.hostKey() == VK_LSHIFT) && 1597 1425 (ke->state() & Qt::ShiftModifier); 1598 1426 /* define hot keys according to the Shift state */ … … 1661 1489 #endif /* Q_WS_PM */ 1662 1490 1663 if (m IsHostkeyPressed && e->type() == QEvent::KeyPress)1491 if (m_bIsHostkeyPressed && e->type() == QEvent::KeyPress) 1664 1492 { 1665 1493 if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12) … … 1684 1512 Assert (0); 1685 1513 1686 CKeyboard keyboard = m Console.GetKeyboard();1514 CKeyboard keyboard = m_console.GetKeyboard(); 1687 1515 keyboard.PutScancodes (combo); 1688 1516 } 1517 #if 0 1518 // TODO check that! 1689 1519 else if (ke->key() == Qt::Key_Home) 1690 1520 { 1691 1521 /* Activate the main menu */ 1692 if (m MainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen())1693 m MainWnd->popupMainMenu (mMouseCaptured);1522 if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()) 1523 machineWindowWrapper()->popupMainMenu (m_bIsMouseCaptured); 1694 1524 else 1695 1525 { … … 1701 1531 QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt, 1702 1532 Qt::NoModifier); 1703 QApplication::sendEvent (m MainWnd->menuBar(), &e1);1704 QApplication::sendEvent (m MainWnd->menuBar(), &e2);1533 QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e1); 1534 QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e2); 1705 1535 } 1706 1536 } … … 1710 1540 * (as in case of non-alphanumeric keys) */ 1711 1541 processHotKey (QKeySequence (ke->key()), 1712 m MainWnd->menuBar()->actions());1542 machineWindowWrapper()->menuBar()->actions()); 1713 1543 } 1544 #endif 1714 1545 } 1715 else if (!m IsHostkeyPressed && e->type() == QEvent::KeyRelease)1546 else if (!m_bIsHostkeyPressed && e->type() == QEvent::KeyRelease) 1716 1547 { 1717 1548 /* Show a possible warning on key release which seems to 1718 1549 * be more expected by the end user */ 1719 1550 1720 if ( isPaused())1551 if (machineWindowWrapper()->machineLogic()->isPaused()) 1721 1552 { 1722 1553 /* if the reminder is disabled we pass the event to … … 1758 1589 } 1759 1590 1760 #ifdef VBOX_WITH_VIDEOHWACCEL 1761 void VBoxConsoleView::scrollContentsBy (int dx, int dy) 1762 { 1763 if (mAttached && mFrameBuf) 1764 { 1765 mFrameBuf->viewportScrolled(dx, dy); 1766 } 1767 QAbstractScrollArea::scrollContentsBy (dx, dy); 1768 } 1769 #endif 1770 1771 1772 bool VBoxConsoleView::eventFilter (QObject *watched, QEvent *e) 1773 { 1774 if (mAttached && watched == viewport()) 1591 bool UIMachineView::eventFilter(QObject *watched, QEvent *e) 1592 { 1593 if (watched == viewport()) 1775 1594 { 1776 1595 switch (e->type()) … … 1841 1660 case QEvent::Resize: 1842 1661 { 1843 if (m MouseCaptured)1662 if (m_bIsMouseCaptured) 1844 1663 updateMouseClipping(); 1845 1664 #ifdef VBOX_WITH_VIDEOHWACCEL … … 1855 1674 } 1856 1675 } 1857 else if (watched == m MainWnd)1676 else if (watched == machineWindowWrapper()->machineWindow()) 1858 1677 { 1859 1678 switch (e->type()) … … 1906 1725 break; 1907 1726 #endif /* defined (Q_WS_MAC) */ 1727 #if 0 1728 // TODO check that! 1908 1729 case QEvent::Resize: 1909 1730 { 1910 1731 /* Set the "guest needs to resize" hint. This hint is acted upon 1911 1732 * when (and only when) the autoresize property is "true". */ 1912 mDoResize = m GuestSupportsGraphics || mMainWnd->isTrueFullscreen();1913 if (!m IgnoreMainwndResize&&1914 m GuestSupportsGraphics && mAutoresizeGuest)1733 mDoResize = m_bIsGuestSupportsGraphics || machineWindowWrapper()->isTrueFullscreen(); 1734 if (!m_bIsMachineWindowResizeIgnored && 1735 m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled) 1915 1736 QTimer::singleShot (300, this, SLOT (doResizeHint())); 1916 1737 break; 1917 1738 } 1739 #endif 1918 1740 case QEvent::WindowStateChange: 1919 1741 { 1920 /* During minimizing and state restoring m MainWndgets the focus1742 /* During minimizing and state restoring machineWindowWrapper() gets the focus 1921 1743 * which belongs to console view window, so returning it properly. */ 1922 1744 QWindowStateChangeEvent *ev = static_cast <QWindowStateChangeEvent*> (e); … … 1937 1759 } 1938 1760 } 1939 else if (watched == mMainWnd->menuBar()) 1761 #if 0 // TODO check that 1762 else if (watched == machineWindowWrapper()->menuBar()) 1940 1763 { 1941 1764 /* … … 1957 1780 QKeyEvent *ke = (QKeyEvent *) e; 1958 1781 if (ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier)) 1959 if (m MainWnd->menuBar()->hasFocus())1782 if (machineWindowWrapper()->menuBar()->hasFocus()) 1960 1783 setFocus(); 1961 1784 break; … … 1965 1788 } 1966 1789 } 1790 #endif 1967 1791 1968 1792 return QAbstractScrollArea::eventFilter (watched, e); … … 1971 1795 #if defined(Q_WS_WIN32) 1972 1796 1973 /** 1974 * Low-level keyboard event handler, 1975 * @return 1976 * true to indicate that the message is processed and false otherwise 1977 */ 1978 bool VBoxConsoleView::winLowKeyboardEvent (UINT msg, const KBDLLHOOKSTRUCT &event) 1979 { 1980 #if 0 1981 LogFlow (("### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X (mKbdCaptured=%d)\n", 1982 event.vkCode, event.scanCode, event.flags, event.dwExtraInfo, mKbdCaptured)); 1983 char buf [256]; 1984 sprintf (buf, "### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X", 1985 event.vkCode, event.scanCode, event.flags, event.dwExtraInfo); 1986 mMainWnd->statusBar()->message (buf); 1987 #endif 1988 1797 bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event) 1798 { 1989 1799 /* Sometimes it happens that Win inserts additional events on some key 1990 1800 * press/release. For example, it prepends ALT_GR in German layout with … … 2005 1815 } 2006 1816 2007 if (!m KbdCaptured)1817 if (!m_bIsKeyboardCaptured) 2008 1818 return false; 2009 1819 … … 2012 1822 * and return false to let Windows process the message normally and update 2013 1823 * its key state table (to avoid the stuck key effect). */ 2014 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) 2015 ? IsExtKeyPressed 2016 : IsKeyPressed; 1824 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed; 2017 1825 if ((event.flags & 0x80) /* released */ && 2018 ((event.vkCode == gs.hostKey() && !hostkey_in_capture) ||1826 ((event.vkCode == m_globalSettings.hostKey() && !hostkey_in_capture) || 2019 1827 (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed)) 2020 1828 return false; … … 2024 1832 message.message = msg; 2025 1833 message.wParam = event.vkCode; 2026 message.lParam = 2027 1 | 2028 (event.scanCode & 0xFF) << 16 | 2029 (event.flags & 0xFF) << 24; 1834 message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24; 2030 1835 2031 1836 /* Windows sets here the extended bit when the Right Shift key is pressed, … … 2036 1841 /* we suppose here that this hook is always called on the main GUI thread */ 2037 1842 long dummyResult; 2038 return winEvent (&message, &dummyResult); 2039 } 2040 2041 /** 2042 * Get Win32 messages before they are passed to Qt. This allows us to get 2043 * the keyboard events directly and bypass the harmful Qt translation. A 2044 * return value of @c true indicates to Qt that the event has been handled. 2045 */ 2046 bool VBoxConsoleView::winEvent (MSG *aMsg, long* /* aResult */) 2047 { 2048 if (!mAttached || ! ( 2049 aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN || 2050 aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP 2051 )) 1843 return winEvent(&message, &dummyResult); 1844 } 1845 1846 bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */) 1847 { 1848 if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN || 1849 aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP)) 2052 1850 return false; 2053 1851 2054 /* check for the special flag possibly set at the end of this function */1852 /* Check for the special flag possibly set at the end of this function */ 2055 1853 if (aMsg->lParam & (0x1 << 25)) 2056 1854 { … … 2058 1856 return false; 2059 1857 } 2060 2061 #if 02062 char buf [256];2063 sprintf (buf, "WM_%04X: vk=%04X rep=%05d scan=%02X ext=%01d rzv=%01X ctx=%01d prev=%01d tran=%01d",2064 aMsg->message, aMsg->wParam,2065 (aMsg->lParam & 0xFFFF),2066 ((aMsg->lParam >> 16) & 0xFF),2067 ((aMsg->lParam >> 24) & 0x1),2068 ((aMsg->lParam >> 25) & 0xF),2069 ((aMsg->lParam >> 29) & 0x1),2070 ((aMsg->lParam >> 30) & 0x1),2071 ((aMsg->lParam >> 31) & 0x1));2072 mMainWnd->statusBar()->message (buf);2073 LogFlow (("%s\n", buf));2074 #endif2075 1858 2076 1859 int scan = (aMsg->lParam >> 16) & 0x7F; … … 2128 1911 } 2129 1912 2130 bool result = keyEvent 2131 if (!result && m KbdCaptured)1913 bool result = keyEvent(vkey, scan, flags); 1914 if (!result && m_bIsKeyboardCaptured) 2132 1915 { 2133 1916 /* keyEvent() returned that it didn't process the message, but since the … … 2136 1919 * shortcuts for example). So send it direcltly to the window with the 2137 1920 * special flag in the reserved area of lParam (to avoid recursion). */ 2138 ::SendMessage 2139 1921 ::SendMessage(aMsg->hwnd, aMsg->message, 1922 aMsg->wParam, aMsg->lParam | (0x1 << 25)); 2140 1923 return true; 2141 1924 } … … 2151 1934 #elif defined (Q_WS_PM) 2152 1935 2153 /** 2154 * Get PM messages before they are passed to Qt. This allows us to get 2155 * the keyboard events directly and bypass the harmful Qt translation. A 2156 * return value of @c true indicates to Qt that the event has been handled. 2157 */ 2158 bool VBoxConsoleView::pmEvent (QMSG *aMsg) 2159 { 2160 if (!mAttached) 1936 bool UIMachineView::pmEvent(QMSG *aMsg) 1937 { 1938 if (aMsg->msg == UM_PREACCEL_CHAR) 1939 { 1940 /* We are inside the input hook 1941 * let the message go through the normal system pipeline. */ 1942 if (!m_bIsKeyboardCaptured) 1943 return false; 1944 } 1945 1946 if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR) 2161 1947 return false; 2162 1948 2163 if (aMsg->msg == UM_PREACCEL_CHAR) 2164 { 2165 /* we are inside the input hook */ 2166 2167 /* let the message go through the normal system pipeline */ 2168 if (!mKbdCaptured) 2169 return false; 2170 } 2171 2172 if (aMsg->msg != WM_CHAR && 2173 aMsg->msg != UM_PREACCEL_CHAR) 1949 /* check for the special flag possibly set at the end of this function */ 1950 if (SHORT2FROMMP(aMsg->mp2) & 0x8000) 1951 { 1952 aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000); 2174 1953 return false; 2175 2176 /* check for the special flag possibly set at the end of this function */ 2177 if (SHORT2FROMMP (aMsg->mp2) & 0x8000) 2178 { 2179 aMsg->mp2 = MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), 2180 SHORT2FROMMP (aMsg->mp2) & ~0x8000); 2181 return false; 2182 } 2183 2184 #if 0 2185 { 2186 char buf [256]; 2187 sprintf (buf, "*** %s: f=%04X rep=%03d scan=%02X ch=%04X vk=%04X", 2188 (aMsg->msg == WM_CHAR ? "WM_CHAR" : "UM_PREACCEL_CHAR"), 2189 SHORT1FROMMP (aMsg->mp1), CHAR3FROMMP (aMsg->mp1), 2190 CHAR4FROMMP (aMsg->mp1), SHORT1FROMMP (aMsg->mp2), 2191 SHORT2FROMMP (aMsg->mp2)); 2192 mMainWnd->statusBar()->message (buf); 2193 LogFlow (("%s\n", buf)); 2194 } 2195 #endif 2196 2197 USHORT ch = SHORT1FROMMP (aMsg->mp2); 2198 USHORT f = SHORT1FROMMP (aMsg->mp1); 2199 2200 int scan = (unsigned int) CHAR4FROMMP (aMsg->mp1); 1954 } 1955 1956 USHORT ch = SHORT1FROMMP(aMsg->mp2); 1957 USHORT f = SHORT1FROMMP(aMsg->mp1); 1958 1959 int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1); 2201 1960 if (!scan || scan > 0x7F) 2202 1961 return true; 2203 1962 2204 int vkey = QIHotKeyEdit::virtualKey 1963 int vkey = QIHotKeyEdit::virtualKey(aMsg); 2205 1964 2206 1965 int flags = 0; … … 2250 2009 2251 2010 bool result = keyEvent (vkey, scan, flags); 2252 if (!result && m KbdCaptured)2011 if (!result && m_bIsKeyboardCaptured) 2253 2012 { 2254 2013 /* keyEvent() returned that it didn't process the message, but since the … … 2257 2016 * shortcuts for example). So send it direcltly to the window with the 2258 2017 * special flag in the reserved area of lParam (to avoid recursion). */ 2259 ::WinSendMsg (aMsg->hwnd, WM_CHAR, 2260 aMsg->mp1, 2261 MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), 2262 SHORT2FROMMP (aMsg->mp2) | 0x8000)); 2018 ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1, 2019 MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000)); 2263 2020 return true; 2264 2021 } … … 2268 2025 #elif defined(Q_WS_X11) 2269 2026 2270 /** 2271 * This function is a "predicate" for XCheckIfEvent(). It will check 2272 * the XEvent passed to it to see if it is a keypress event matching 2273 * the keyrelease event in @a pvArg. 2274 * @returns True if the event matches, False otherwise 2275 * @param pEvent the event to compare, taken from the event queue 2276 * @param pvArg the keyrelease event we would like to compare against 2277 */ 2278 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, 2279 XPointer pvArg) 2027 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg) 2280 2028 { 2281 2029 XEvent *pKeyEvent = (XEvent *) pvArg; 2282 if ((pEvent->type == XKeyPress) && 2283 (pEvent->xkey.keycode == pKeyEvent->xkey.keycode)) 2030 if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode)) 2284 2031 return True; 2285 2032 else … … 2287 2034 } 2288 2035 2289 /** 2290 * This routine gets X11 events before they are processed by Qt. This is 2291 * used for our platform specific keyboard implementation. A return value 2292 * of TRUE indicates that the event has been processed by us. 2293 */ 2294 bool VBoxConsoleView::x11Event (XEvent *event) 2036 bool UIMachineView::x11Event(XEvent *event) 2295 2037 { 2296 2038 switch (event->type) 2297 2039 { 2298 2040 /* We have to handle XFocusOut right here as this event is not passed 2299 * to VBoxConsoleView::event(). Handling this event is important for2041 * to UIMachineView::event(). Handling this event is important for 2300 2042 * releasing the keyboard before the screen saver gets active. */ 2301 2043 case XFocusOut: 2302 2044 case XFocusIn: 2303 2045 if (isRunning()) 2304 focusEvent 2046 focusEvent(event->type == XFocusIn); 2305 2047 return false; 2306 2048 case XKeyPress: 2307 2049 case XKeyRelease: 2308 if (mAttached) 2309 break; 2310 /* else fall through */ 2050 break; 2311 2051 default: 2312 2052 return false; /* pass the event to Qt */ … … 2314 2054 2315 2055 /* Translate the keycode to a PC scan code. */ 2316 unsigned scan = handleXKeyEvent (event); 2317 2318 #if 0 2319 char buf [256]; 2320 sprintf (buf, "pr=%d kc=%08X st=%08X extended=%s scan=%04X", 2321 event->type == XKeyPress ? 1 : 0, event->xkey.keycode, 2322 event->xkey.state, scan >> 8 ? "true" : "false", scan & 0x7F); 2323 mMainWnd->statusBar()->message (buf); 2324 LogFlow (("### %s\n", buf)); 2325 #endif 2056 unsigned scan = handleXKeyEvent(event); 2326 2057 2327 2058 // scancodes 0x00 (no valid translation) and 0x80 are ignored … … 2333 2064 * XKeyRelease before the XKeyPress. */ 2334 2065 XEvent returnEvent; 2335 if ((event->type == XKeyRelease) && 2336 (XCheckIfEvent(event->xkey.display, &returnEvent,2337 VBoxConsoleViewCompEvent, (XPointer) event) == True)){2066 if ((event->type == XKeyRelease) && (XCheckIfEvent(event->xkey.display, &returnEvent, 2067 VBoxConsoleViewCompEvent, (XPointer) event) == True)) 2068 { 2338 2069 XPutBackEvent(event->xkey.display, &returnEvent); 2339 2070 /* Discard it, don't pass it to Qt. */ … … 2341 2072 } 2342 2073 2343 KeySym ks = ::XKeycodeToKeysym 2074 KeySym ks = ::XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0); 2344 2075 2345 2076 int flags = 0; … … 2358 2089 break; 2359 2090 case XK_Pause: 2360 if (event->xkey.state & ControlMask) /* Break */ 2361 { 2362 ks = XK_Break; 2363 flags |= KeyExtended; 2364 scan = 0x46; 2365 } 2366 else 2367 flags |= KeyPause; 2091 flags |= KeyPause; 2368 2092 break; 2369 2093 } 2370 2094 2371 return keyEvent 2095 return keyEvent(ks, scan, flags); 2372 2096 } 2373 2097 2374 2098 #elif defined (Q_WS_MAC) 2375 2099 2376 /** 2377 * Invoked by VBoxConsoleView::darwinEventHandlerProc / VBoxConsoleView::macEventFilter when 2378 * it receives a raw keyboard event. 2379 * 2380 * @param pvCocoaEvent The Cocoa keyboard event. Can be NULL in some configs. 2381 * @param inEvent The keyboard event. 2382 * 2383 * @return true if the key was processed, false if it wasn't processed and should be passed on. 2384 */ 2385 bool VBoxConsoleView::darwinKeyboardEvent (const void *pvCocoaEvent, EventRef inEvent) 2100 bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent) 2386 2101 { 2387 2102 bool ret = false; 2388 UInt32 EventKind = ::GetEventKind 2103 UInt32 EventKind = ::GetEventKind(inEvent); 2389 2104 if (EventKind != kEventRawKeyModifiersChanged) 2390 2105 { 2391 2106 /* convert keycode to set 1 scan code. */ 2392 2107 UInt32 keyCode = ~0U; 2393 ::GetEventParameter 2394 unsigned scanCode = ::DarwinKeycodeToSet1Scancode 2108 ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode); 2109 unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode); 2395 2110 if (scanCode) 2396 2111 { … … 2405 2120 2406 2121 /* get the unicode string (if present). */ 2407 AssertCompileSize 2408 AssertCompileSize 2122 AssertCompileSize(wchar_t, 2); 2123 AssertCompileSize(UniChar, 2); 2409 2124 ByteCount cbWritten = 0; 2410 2125 wchar_t ucs[8]; 2411 if (::GetEventParameter 2412 sizeof(ucs), &cbWritten, &ucs[0]) != 0)2126 if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 2127 sizeof(ucs), &cbWritten, &ucs[0]) != 0) 2413 2128 cbWritten = 0; 2414 2129 ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */ 2415 2130 2416 ret = keyEvent 2131 ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL); 2417 2132 } 2418 2133 } … … 2421 2136 /* May contain multiple modifier changes, kind of annoying. */ 2422 2137 UInt32 newMask = 0; 2423 ::GetEventParameter 2424 sizeof(newMask), NULL, &newMask);2425 newMask = ::DarwinAdjustModifierMask 2138 ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, 2139 sizeof(newMask), NULL, &newMask); 2140 newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent); 2426 2141 UInt32 changed = newMask ^ mDarwinKeyModifiers; 2427 2142 if (changed) … … 2431 2146 if (!(changed & (1 << bit))) 2432 2147 continue; 2433 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode 2148 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit); 2434 2149 if (!scanCode) 2435 2150 continue; 2436 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode 2437 Assert 2151 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit); 2152 Assert(keyCode); 2438 2153 2439 2154 if (!(scanCode & VBOXKEY_LOCK)) … … 2443 2158 flags |= KeyExtended; 2444 2159 scanCode &= VBOXKEY_SCANCODE_MASK; 2445 ret |= keyEvent 2160 ret |= keyEvent(keyCode, scanCode & 0xff, flags); 2446 2161 } 2447 2162 else … … 2451 2166 flags |= KeyExtended; 2452 2167 scanCode &= VBOXKEY_SCANCODE_MASK; 2453 keyEvent 2454 keyEvent 2168 keyEvent(keyCode, scanCode, flags | KeyPressed); 2169 keyEvent(keyCode, scanCode, flags); 2455 2170 } 2456 2171 } … … 2467 2182 } 2468 2183 2469 2470 /** 2471 * Installs or removes the keyboard event handler. 2472 * 2473 * @param fGrab True if we're to grab the events, false if we're not to. 2474 */ 2475 void VBoxConsoleView::darwinGrabKeyboardEvents (bool fGrab) 2184 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab) 2476 2185 { 2477 2186 mKeyboardGrabbed = fGrab; 2478 2187 if (fGrab) 2479 2188 { 2480 /* Disable mouse and keyboard event compression/delaying to make sure 2481 we *really* get all of the events. */ 2482 ::CGSetLocalEventsSuppressionInterval (0.0); 2483 setMouseCoalescingEnabled (false); 2189 /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */ 2190 ::CGSetLocalEventsSuppressionInterval(0.0); 2191 setMouseCoalescingEnabled(false); 2484 2192 2485 2193 /* Register the event callback/hook and grab the keyboard. */ 2486 2194 # ifdef QT_MAC_USE_COCOA 2487 2195 ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */ 2488 VBoxConsoleView::darwinEventHandlerProc, this);2196 UIMachineView::darwinEventHandlerProc, this); 2489 2197 2490 2198 # elif !defined (VBOX_WITH_HACKED_QT) … … 2505 2213 eventTypes[5].eventKind = kEventCommandUpdateStatus; 2506 2214 2507 EventHandlerUPP eventHandler = ::NewEventHandlerUPP (VBoxConsoleView::darwinEventHandlerProc);2215 EventHandlerUPP eventHandler = ::NewEventHandlerUPP(UIMachineView::darwinEventHandlerProc); 2508 2216 2509 2217 mDarwinEventHandlerRef = NULL; 2510 ::InstallApplicationEventHandler 2511 2512 ::DisposeEventHandlerUPP 2218 ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 2219 this, &mDarwinEventHandlerRef); 2220 ::DisposeEventHandlerUPP(eventHandler); 2513 2221 2514 2222 # else /* VBOX_WITH_HACKED_QT */ 2515 ((QIApplication *)qApp)->setEventFilter (VBoxConsoleView::macEventFilter, this);2223 ((QIApplication *)qApp)->setEventFilter(UIMachineView::macEventFilter, this); 2516 2224 # endif /* VBOX_WITH_HACKED_QT */ 2517 2225 … … 2522 2230 ::DarwinReleaseKeyboard(); 2523 2231 # ifdef QT_MAC_USE_COCOA 2524 ::VBoxCocoaApplication_unsetCallback 2525 VBoxConsoleView::darwinEventHandlerProc, this);2232 ::VBoxCocoaApplication_unsetCallback(UINT32_MAX, /** @todo fix mask */ 2233 UIMachineView::darwinEventHandlerProc, this); 2526 2234 # elif !defined(VBOX_WITH_HACKED_QT) 2527 2235 if (mDarwinEventHandlerRef) 2528 2236 { 2529 ::RemoveEventHandler 2237 ::RemoveEventHandler(mDarwinEventHandlerRef); 2530 2238 mDarwinEventHandlerRef = NULL; 2531 2239 } 2532 2240 # else /* VBOX_WITH_HACKED_QT */ 2533 ((QIApplication *)qApp)->setEventFilter 2241 ((QIApplication *)qApp)->setEventFilter(NULL, NULL); 2534 2242 # endif /* VBOX_WITH_HACKED_QT */ 2535 2243 } 2536 2244 } 2537 2245 2538 #endif // defined (Q_WS_MAC) 2539 2540 // 2541 // Private members 2542 ///////////////////////////////////////////////////////////////////////////// 2543 2544 /** 2545 * Called on every focus change and also to forcibly capture/uncapture the 2546 * input in situations similar to gaining or losing focus. 2547 * 2548 * @param aHasFocus true if the window got focus and false otherwise. 2549 * @param aReleaseHostKey true to release the host key (used only when 2550 * @a aHasFocus is false. 2551 */ 2552 void VBoxConsoleView::focusEvent (bool aHasFocus, 2553 bool aReleaseHostKey /* = true */) 2246 #endif 2247 2248 #if defined (Q_WS_WIN32) 2249 static HHOOK gKbdHook = NULL; 2250 static UIMachineView *gView = 0; 2251 LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 2252 { 2253 Assert (gView); 2254 if (gView && nCode == HC_ACTION && 2255 gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam)) 2256 return 1; 2257 2258 return CallNextHookEx (NULL, nCode, wParam, lParam); 2259 } 2260 #endif 2261 2262 #if defined (Q_WS_MAC) 2263 # if defined (QT_MAC_USE_COCOA) 2264 bool UIMachineView::darwinEventHandlerProc (const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser) 2265 { 2266 UIMachineView *view = (UIMachineView*)pvUser; 2267 EventRef inEvent = (EventRef)pvCarbonEvent; 2268 UInt32 eventClass = ::GetEventClass(inEvent); 2269 2270 /* Check if this is an application key combo. In that case we will not pass 2271 the event to the guest, but let the host process it. */ 2272 if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent)) 2273 return false; 2274 2275 /* All keyboard class events needs to be handled. */ 2276 if (eventClass == kEventClassKeyboard) 2277 { 2278 if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent)) 2279 return true; 2280 } 2281 /* Pass the event along. */ 2282 return false; 2283 } 2284 2285 # elif !defined (VBOX_WITH_HACKED_QT) 2286 2287 pascal OSStatus UIMachineView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 2288 { 2289 UIMachineView *view = static_cast<UIMachineView *> (inUserData); 2290 UInt32 eventClass = ::GetEventClass (inEvent); 2291 2292 /* Not sure but this seems an triggered event if the spotlight searchbar is 2293 * displayed. So flag that the host key isn't pressed alone. */ 2294 if (eventClass == 'cgs ' && view->m_bIsHostkeyPressed && ::GetEventKind (inEvent) == 0x15) 2295 view->m_bIsHostkeyAlone = false; 2296 2297 if (eventClass == kEventClassKeyboard) 2298 { 2299 if (view->darwinKeyboardEvent (NULL, inEvent)) 2300 return 0; 2301 } 2302 2303 /* 2304 * Command-H and Command-Q aren't properly disabled yet, and it's still 2305 * possible to use the left command key to invoke them when the keyboard 2306 * is captured. We discard the events these if the keyboard is captured 2307 * as a half measure to prevent unexpected behaviour. However, we don't 2308 * get any key down/up events, so these combinations are dead to the guest... 2309 */ 2310 else if (eventClass == kEventClassCommand) 2311 { 2312 if (view->m_bIsKeyboardCaptured) 2313 return 0; 2314 } 2315 return ::CallNextEventHandler(inHandlerCallRef, inEvent); 2316 } 2317 2318 # else /* VBOX_WITH_HACKED_QT */ 2319 2320 bool UIMachineView::macEventFilter(EventRef inEvent, void *inUserData) 2321 { 2322 UIMachineView *view = static_cast<UIMachineView *>(inUserData); 2323 UInt32 eventClass = ::GetEventClass(inEvent); 2324 UInt32 eventKind = ::GetEventKind(inEvent); 2325 2326 /* Not sure but this seems an triggered event if the spotlight searchbar is 2327 * displayed. So flag that the host key isn't pressed alone. */ 2328 if (eventClass == 'cgs ' && eventKind == 0x15 && 2329 view->m_bIsHostkeyPressed) 2330 view->m_bIsHostkeyAlone = false; 2331 2332 if (eventClass == kEventClassKeyboard) 2333 { 2334 if (view->darwinKeyboardEvent (NULL, inEvent)) 2335 return true; 2336 } 2337 return false; 2338 } 2339 # endif /* VBOX_WITH_HACKED_QT */ 2340 2341 #endif /* Q_WS_MAC */ 2342 2343 void UIMachineView::focusEvent(bool aHasFocus, bool aReleaseHostKey /* = true */) 2554 2344 { 2555 2345 if (aHasFocus) 2556 2346 { 2557 2347 #ifdef RT_OS_WINDOWS 2558 if ( !mDisableAutoCapture && gs.autoCapture() 2559 && GetAncestor (winId(), GA_ROOT) == GetForegroundWindow()) 2348 if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture() && GetAncestor(winId(), GA_ROOT) == GetForegroundWindow()) 2560 2349 #else 2561 if (!m DisableAutoCapture &&gs.autoCapture())2350 if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture()) 2562 2351 #endif /* RT_OS_WINDOWS */ 2563 2352 { 2564 captureKbd (true); 2565 /// @todo (dmik) 2566 // the below is for the mouse auto-capture. disabled for now. in order to 2567 // properly support it, we need to know when *all* mouse buttons are 2568 // released after we got focus, and grab the mouse only after then. 2569 // btw, the similar would be good the for keyboard auto-capture, too. 2570 // if (!(mMouseAbsolute && mMouseIntegration)) 2571 // captureMouse (true); 2353 captureKbd(true); 2572 2354 } 2573 2355 2574 2356 /* reset the single-time disable capture flag */ 2575 if (m DisableAutoCapture)2576 m DisableAutoCapture= false;2357 if (m_bIsAutoCaptureDisabled) 2358 m_bIsAutoCaptureDisabled = false; 2577 2359 } 2578 2360 else 2579 2361 { 2580 captureMouse (false); 2581 captureKbd (false, false); 2582 releaseAllPressedKeys (aReleaseHostKey); 2583 } 2584 } 2585 2586 /** 2587 * Synchronize the views of the host and the guest to the modifier keys. 2588 * This function will add up to 6 additional keycodes to codes. 2589 * 2590 * @param codes pointer to keycodes which are sent to the keyboard 2591 * @param count pointer to the keycodes counter 2592 */ 2593 void VBoxConsoleView::fixModifierState (LONG *codes, uint *count) 2594 { 2595 #if defined(Q_WS_X11) 2596 2597 Window wDummy1, wDummy2; 2598 int iDummy3, iDummy4, iDummy5, iDummy6; 2599 unsigned uMask; 2600 unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0; 2601 2602 uKeyMaskCaps = LockMask; 2603 XModifierKeymap* map = XGetModifierMapping(QX11Info::display()); 2604 KeyCode keyCodeNum = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock); 2605 KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock); 2606 2607 for (int i = 0; i < 8; i++) 2608 { 2609 if ( keyCodeNum != NoSymbol 2610 && map->modifiermap[map->max_keypermod * i] == keyCodeNum) 2611 uKeyMaskNum = 1 << i; 2612 else if ( keyCodeScroll != NoSymbol 2613 && map->modifiermap[map->max_keypermod * i] == keyCodeScroll) 2614 uKeyMaskScroll = 1 << i; 2615 } 2616 XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2, 2617 &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask); 2618 XFreeModifiermap(map); 2619 2620 if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum))) 2621 { 2622 muNumLockAdaptionCnt--; 2623 codes[(*count)++] = 0x45; 2624 codes[(*count)++] = 0x45 | 0x80; 2625 } 2626 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps))) 2627 { 2628 muCapsLockAdaptionCnt--; 2629 codes[(*count)++] = 0x3a; 2630 codes[(*count)++] = 0x3a | 0x80; 2631 /* Some keyboard layouts require shift to be pressed to break 2632 * capslock. For simplicity, only do this if shift is not 2633 * already held down. */ 2634 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2635 { 2636 codes[(*count)++] = 0x2a; 2637 codes[(*count)++] = 0x2a | 0x80; 2638 } 2639 } 2640 2641 #elif defined(Q_WS_WIN32) 2642 2643 if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK)))) 2644 { 2645 muNumLockAdaptionCnt--; 2646 codes[(*count)++] = 0x45; 2647 codes[(*count)++] = 0x45 | 0x80; 2648 } 2649 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL)))) 2650 { 2651 muCapsLockAdaptionCnt--; 2652 codes[(*count)++] = 0x3a; 2653 codes[(*count)++] = 0x3a | 0x80; 2654 /* Some keyboard layouts require shift to be pressed to break 2655 * capslock. For simplicity, only do this if shift is not 2656 * already held down. */ 2657 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2658 { 2659 codes[(*count)++] = 0x2a; 2660 codes[(*count)++] = 0x2a | 0x80; 2661 } 2662 } 2663 2664 #elif defined (Q_WS_MAC) 2665 2666 /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */ 2667 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock))) 2668 { 2669 muCapsLockAdaptionCnt--; 2670 codes[(*count)++] = 0x3a; 2671 codes[(*count)++] = 0x3a | 0x80; 2672 /* Some keyboard layouts require shift to be pressed to break 2673 * capslock. For simplicity, only do this if shift is not 2674 * already held down. */ 2675 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2676 { 2677 codes[(*count)++] = 0x2a; 2678 codes[(*count)++] = 0x2a | 0x80; 2679 } 2680 } 2681 2682 #else 2683 2684 //#warning Adapt VBoxConsoleView::fixModifierState 2685 2686 #endif 2687 2688 2689 } 2690 2691 /** 2692 * Called on enter/exit seamless/fullscreen mode. 2693 */ 2694 void VBoxConsoleView::toggleFSMode (const QSize &aSize) 2695 { 2696 if ((mGuestSupportsGraphics && mAutoresizeGuest) || 2697 mMainWnd->isTrueSeamless() || 2698 mMainWnd->isTrueFullscreen()) 2699 { 2700 QSize newSize; 2701 if (aSize.isValid()) 2702 { 2703 mNormalSize = aSize; 2704 newSize = maximumSize(); 2705 } 2706 else 2707 newSize = mNormalSize; 2708 doResizeHint (newSize); 2709 } 2710 2711 /* Reactivate the console window to preserve the focus position. 2712 * Else focus will move to the mini-tool-bar. */ 2713 activateWindow(); 2714 } 2715 2716 /** 2717 * Get the current available desktop geometry for the console/framebuffer 2718 * 2719 * @returns the geometry. An empty rectangle means unrestricted. 2720 */ 2721 QRect VBoxConsoleView::desktopGeometry() 2722 { 2723 QRect rc; 2724 switch (mDesktopGeo) 2725 { 2726 case DesktopGeo_Fixed: 2727 case DesktopGeo_Automatic: 2728 rc = QRect (0, 0, 2729 RT_MAX (mDesktopGeometry.width(), mStoredConsoleSize.width()), 2730 RT_MAX (mDesktopGeometry.height(), mStoredConsoleSize.height())); 2731 break; 2732 case DesktopGeo_Any: 2733 rc = QRect (0, 0, 0, 0); 2734 break; 2735 default: 2736 AssertMsgFailed (("Bad geometry type %d\n", mDesktopGeo)); 2737 } 2738 return rc; 2739 } 2740 2741 QRegion VBoxConsoleView::lastVisibleRegion() const 2742 { 2743 return mLastVisibleRegion; 2744 } 2745 2746 bool VBoxConsoleView::isAutoresizeGuestActive() 2747 { 2748 return mGuestSupportsGraphics && mAutoresizeGuest; 2749 } 2750 2751 /** 2752 * Called on every key press and release (while in focus). 2753 * 2754 * @param aKey virtual scan code (virtual key on Win32 and KeySym on X11) 2755 * @param aScan hardware scan code 2756 * @param aFlags flags, a combination of Key* constants 2757 * @param aUniKey Unicode translation of the key. Optional. 2758 * 2759 * @return true to consume the event and false to pass it to Qt 2760 */ 2761 bool VBoxConsoleView::keyEvent (int aKey, uint8_t aScan, int aFlags, 2762 wchar_t *aUniKey/* = NULL*/) 2763 { 2764 #if 0 2765 { 2766 char buf [256]; 2767 sprintf (buf, "aKey=%08X aScan=%02X aFlags=%08X", 2768 aKey, aScan, aFlags); 2769 mMainWnd->statusBar()->message (buf); 2770 } 2771 #endif 2772 2773 const bool isHostKey = aKey == gs.hostKey(); 2774 2775 LONG buf [16]; 2362 captureMouse(false); 2363 captureKbd(false, false); 2364 releaseAllPressedKeys(aReleaseHostKey); 2365 } 2366 } 2367 2368 bool UIMachineView::keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey /* = NULL */) 2369 { 2370 const bool isHostKey = aKey == m_globalSettings.hostKey(); 2371 2372 LONG buf[16]; 2776 2373 LONG *codes = buf; 2777 2374 uint count = 0; 2778 2375 uint8_t whatPressed = 0; 2779 2376 2780 if (!isHostKey && !m IsHostkeyPressed)2377 if (!isHostKey && !m_bIsHostkeyPressed) 2781 2378 { 2782 2379 if (aFlags & KeyPrint) … … 2787 2384 { 2788 2385 codes = PrintMake; 2789 count = SIZEOF_ARRAY 2386 count = SIZEOF_ARRAY(PrintMake); 2790 2387 } 2791 2388 else 2792 2389 { 2793 2390 codes = PrintBreak; 2794 count = SIZEOF_ARRAY 2391 count = SIZEOF_ARRAY(PrintBreak); 2795 2392 } 2796 2393 } … … 2801 2398 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 }; 2802 2399 codes = Pause; 2803 count = SIZEOF_ARRAY 2400 count = SIZEOF_ARRAY(Pause); 2804 2401 } 2805 2402 else … … 2816 2413 * CapsLock, ScrollLock) as the X server. If not, send KeyPress events 2817 2414 * to synchronize the state. */ 2818 fixModifierState 2415 fixModifierState(codes, &count); 2819 2416 } 2820 2417 … … 2835 2432 * keys will be pressed next when one of C, A, D is held. */ 2836 2433 2837 if (isRunning() && m KbdCaptured)2434 if (isRunning() && m_bIsKeyboardCaptured) 2838 2435 { 2839 2436 captureKbd (false); 2840 if (!(m MouseAbsolute && mMouseIntegration))2437 if (!(m_bIsMouseAbsolute && m_bIsMouseIntegrated)) 2841 2438 captureMouse (false); 2842 2439 } … … 2850 2447 if (aFlags & KeyExtended) 2851 2448 { 2852 codes 2449 codes[count++] = 0xE0; 2853 2450 whatPressed = IsExtKeyPressed; 2854 2451 } … … 2856 2453 if (aFlags & KeyPressed) 2857 2454 { 2858 codes 2859 mPressedKeys 2455 codes[count++] = aScan; 2456 mPressedKeys[aScan] |= whatPressed; 2860 2457 } 2861 2458 else … … 2865 2462 if (!(mPressedKeys [aScan] & whatPressed)) 2866 2463 return true; 2867 codes 2868 mPressedKeys 2869 } 2870 2871 if (m KbdCaptured)2872 mPressedKeys 2464 codes[count++] = aScan | 0x80; 2465 mPressedKeys[aScan] &= ~whatPressed; 2466 } 2467 2468 if (m_bIsKeyboardCaptured) 2469 mPressedKeys[aScan] |= IsKbdCaptured; 2873 2470 else 2874 mPressedKeys 2471 mPressedKeys[aScan] &= ~IsKbdCaptured; 2875 2472 } 2876 2473 } … … 2878 2475 { 2879 2476 /* currently this is used in winLowKeyboardEvent() only */ 2880 hostkey_in_capture = m KbdCaptured;2477 hostkey_in_capture = m_bIsKeyboardCaptured; 2881 2478 } 2882 2479 … … 2889 2486 if (isHostKey) 2890 2487 { 2891 if (!m IsHostkeyPressed)2892 { 2893 m IsHostkeyPressed = mIsHostkeyAlone = true;2488 if (!m_bIsHostkeyPressed) 2489 { 2490 m_bIsHostkeyPressed = m_bIsHostkeyAlone = true; 2894 2491 if (isRunning()) 2895 2492 saveKeyStates(); … … 2899 2496 else 2900 2497 { 2901 if (m IsHostkeyPressed)2902 { 2903 if (m IsHostkeyAlone)2498 if (m_bIsHostkeyPressed) 2499 { 2500 if (m_bIsHostkeyAlone) 2904 2501 { 2905 2502 hotkey = aKey; 2906 m IsHostkeyAlone = false;2503 m_bIsHostkeyAlone = false; 2907 2504 } 2908 2505 } … … 2913 2510 if (isHostKey) 2914 2511 { 2915 if (m IsHostkeyPressed)2916 { 2917 m IsHostkeyPressed = false;2918 2919 if (m IsHostkeyAlone)2512 if (m_bIsHostkeyPressed) 2513 { 2514 m_bIsHostkeyPressed = false; 2515 2516 if (m_bIsHostkeyAlone) 2920 2517 { 2921 if ( isPaused())2518 if (machineWindowWrapper()->machineLogic()->isPaused()) 2922 2519 { 2923 2520 vboxProblem().remindAboutPausedVMInput(); 2924 2521 } 2925 else 2926 if (isRunning()) 2522 else if (isRunning()) 2927 2523 { 2928 bool captured = m KbdCaptured;2524 bool captured = m_bIsKeyboardCaptured; 2929 2525 bool ok = true; 2930 2526 if (!captured) … … 2934 2530 * the capture state is to be defined by the 2935 2531 * dialog result itself */ 2936 m DisableAutoCapture= true;2532 m_bIsAutoCaptureDisabled = true; 2937 2533 bool autoConfirmed = false; 2938 2534 ok = vboxProblem().confirmInputCapture (&autoConfirmed); 2939 2535 if (autoConfirmed) 2940 m DisableAutoCapture= false;2536 m_bIsAutoCaptureDisabled = false; 2941 2537 /* otherwise, the disable flag will be reset in 2942 2538 * the next console view's foucs in event (since … … 2948 2544 { 2949 2545 captureKbd (!captured, false); 2950 if (!(m MouseAbsolute && mMouseIntegration))2546 if (!(m_bIsMouseAbsolute && m_bIsMouseIntegrated)) 2951 2547 { 2952 2548 #ifdef Q_WS_X11 … … 2956 2552 qApp->processEvents(); 2957 2553 #endif 2958 captureMouse (m KbdCaptured);2554 captureMouse (m_bIsKeyboardCaptured); 2959 2555 } 2960 2556 } … … 2970 2566 else 2971 2567 { 2972 if (m IsHostkeyPressed)2973 m IsHostkeyAlone = false;2568 if (m_bIsHostkeyPressed) 2569 m_bIsHostkeyAlone = false; 2974 2570 } 2975 2571 } … … 3000 2596 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 3001 2597 QChar (ch).toUpper().unicode()), 3002 m MainWnd->menuBar()->actions());2598 machineWindowWrapper()->menuBar()->actions()); 3003 2599 } 3004 2600 delete[] list; … … 3018 2614 { 3019 2615 QChar c = QString::fromLocal8Bit (&ch, 1) [0]; 3020 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +3021 c.toUpper().unicode()),3022 mMainWnd->menuBar()->actions());3023 2616 } 3024 2617 } … … 3027 2620 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 3028 2621 QChar (aUniKey [0]).toUpper().unicode()), 3029 m MainWnd->menuBar()->actions());2622 machineWindowWrapper()->menuBar()->actions()); 3030 2623 3031 2624 /* Don't consider the hot key as pressed since the guest never saw … … 3041 2634 3042 2635 /* no more to do, if the host key is in action or the VM is paused */ 3043 if (m IsHostkeyPressed || isHostKey ||isPaused())2636 if (m_bIsHostkeyPressed || isHostKey || machineWindowWrapper()->machineLogic()->isPaused()) 3044 2637 { 3045 2638 /* grab the key from Qt and from VM if it's a host key, … … 3048 2641 } 3049 2642 3050 CKeyboard keyboard = m Console.GetKeyboard();2643 CKeyboard keyboard = m_console.GetKeyboard(); 3051 2644 Assert (!keyboard.isNull()); 3052 2645 … … 3056 2649 #endif 3057 2650 3058 #if 03059 {3060 char buf [256];3061 sprintf (buf, "*** SCANS: ");3062 for (uint i = 0; i < count; ++ i)3063 sprintf (buf + strlen (buf), "%02X ", codes [i]);3064 mMainWnd->statusBar()->message (buf);3065 LogFlow (("%s\n", buf));3066 }3067 #endif3068 3069 2651 std::vector <LONG> scancodes(codes, &codes[count]); 3070 2652 keyboard.PutScancodes (QVector<LONG>::fromStdVector(scancodes)); … … 3074 2656 } 3075 2657 3076 /** 3077 * Called on every mouse/wheel move and button press/release. 3078 * 3079 * @return true to consume the event and false to pass it to Qt 3080 */ 3081 bool VBoxConsoleView::mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos, 3082 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 3083 int aWheelDelta, Qt::Orientation aWheelDir) 2658 bool UIMachineView::mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos, 2659 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 2660 int aWheelDelta, Qt::Orientation aWheelDir) 3084 2661 { 3085 2662 #if 1 3086 3087 2663 LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n", 3088 2664 __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(), … … 3115 2691 /* Simulate the right click on 3116 2692 * Host+Left Mouse */ 3117 if (m IsHostkeyPressed &&3118 m IsHostkeyAlone &&2693 if (m_bIsHostkeyPressed && 2694 m_bIsHostkeyAlone && 3119 2695 state == KMouseButtonState_LeftButton) 3120 2696 state = KMouseButtonState_RightButton; … … 3133 2709 wheelHorizontal = aWheelDelta / 120; 3134 2710 3135 if (m MouseCaptured)2711 if (m_bIsMouseCaptured) 3136 2712 { 3137 2713 #ifdef Q_WS_WIN32 … … 3140 2716 #endif 3141 2717 3142 CMouse mouse = m Console.GetMouse();2718 CMouse mouse = m_console.GetMouse(); 3143 2719 mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(), 3144 2720 aGlobalPos.y() - mLastPos.y(), … … 3234 2810 return true; /* stop further event handling */ 3235 2811 } 3236 else /* !m MouseCaptured */3237 { 3238 if (mMainWnd->isTrueFullscreen())2812 else /* !m_bIsMouseCaptured */ 2813 { 2814 //if (machineWindowWrapper()->isTrueFullscreen()) // TODO check that! 3239 2815 { 3240 2816 if (mode != VBoxDefs::SDLMode) … … 3260 2836 } 3261 2837 3262 if (m MouseAbsolute && mMouseIntegration)2838 if (m_bIsMouseAbsolute && m_bIsMouseIntegrated) 3263 2839 { 3264 2840 int cw = contentsWidth(), ch = contentsHeight(); … … 3285 2861 else if (cpnt.y() > ch) cpnt.setY (ch); 3286 2862 3287 CMouse mouse = m Console.GetMouse();2863 CMouse mouse = m_console.GetMouse(); 3288 2864 mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical, 3289 2865 wheelHorizontal, state); … … 3296 2872 aButtons == Qt::NoButton)) 3297 2873 { 3298 if ( isPaused())2874 if (machineWindowWrapper()->machineLogic()->isPaused()) 3299 2875 { 3300 2876 vboxProblem().remindAboutPausedVMInput(); … … 3306 2882 * the capture state is to be defined by the 3307 2883 * dialog result itself */ 3308 m DisableAutoCapture= true;2884 m_bIsAutoCaptureDisabled = true; 3309 2885 bool autoConfirmed = false; 3310 2886 bool ok = vboxProblem().confirmInputCapture (&autoConfirmed); 3311 2887 if (autoConfirmed) 3312 m DisableAutoCapture= false;2888 m_bIsAutoCaptureDisabled = false; 3313 2889 /* otherwise, the disable flag will be reset in 3314 2890 * the next console view's foucs in event (since … … 3335 2911 } 3336 2912 3337 void VBoxConsoleView::onStateChange (KMachineState state) 2913 void UIMachineView::resizeEvent(QResizeEvent *) 2914 { 2915 updateSliders(); 2916 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 2917 QRect r = viewport()->geometry(); 2918 PostBoundsChanged(r); 2919 #endif /* Q_WS_MAC */ 2920 } 2921 2922 void UIMachineView::moveEvent(QMoveEvent *) 2923 { 2924 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 2925 QRect r = viewport()->geometry(); 2926 PostBoundsChanged (r); 2927 #endif /* Q_WS_MAC */ 2928 } 2929 2930 void UIMachineView::paintEvent(QPaintEvent *pe) 2931 { 2932 if (mPausedShot.isNull()) 2933 { 2934 /* delegate the paint function to the VBoxFrameBuffer interface */ 2935 if (mFrameBuf) 2936 mFrameBuf->paintEvent(pe); 2937 #ifdef Q_WS_MAC 2938 /* Update the dock icon if we are in the running state */ 2939 if (isRunning()) 2940 updateDockIcon(); 2941 #endif 2942 return; 2943 } 2944 2945 #ifdef VBOX_GUI_USE_QUARTZ2D 2946 if (mode == VBoxDefs::Quartz2DMode && mFrameBuf) 2947 { 2948 mFrameBuf->paintEvent(pe); 2949 updateDockIcon(); 2950 } 2951 else 2952 #endif 2953 { 2954 /* We have a snapshot for the paused state: */ 2955 QRect r = pe->rect().intersect (viewport()->rect()); 2956 /* We have to disable paint on screen if we are using the regular painter */ 2957 bool paintOnScreen = viewport()->testAttribute(Qt::WA_PaintOnScreen); 2958 viewport()->setAttribute(Qt::WA_PaintOnScreen, false); 2959 QPainter pnt(viewport()); 2960 pnt.drawPixmap(r.x(), r.y(), mPausedShot, 2961 r.x() + contentsX(), r.y() + contentsY(), 2962 r.width(), r.height()); 2963 /* Restore the attribute to its previous state */ 2964 viewport()->setAttribute(Qt::WA_PaintOnScreen, paintOnScreen); 2965 #ifdef Q_WS_MAC 2966 updateDockIcon(); 2967 #endif 2968 } 2969 } 2970 2971 void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount) 2972 { 2973 /* Synchronize the views of the host and the guest to the modifier keys. 2974 * This function will add up to 6 additional keycodes to codes. */ 2975 2976 #if defined (Q_WS_X11) 2977 2978 Window wDummy1, wDummy2; 2979 int iDummy3, iDummy4, iDummy5, iDummy6; 2980 unsigned uMask; 2981 unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0; 2982 2983 uKeyMaskCaps = LockMask; 2984 XModifierKeymap* map = XGetModifierMapping(QX11Info::display()); 2985 KeyCode keyCodeNum = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock); 2986 KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock); 2987 2988 for (int i = 0; i < 8; ++ i) 2989 { 2990 if (keyCodeNum != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeNum) 2991 uKeyMaskNum = 1 << i; 2992 else if (keyCodeScroll != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeScroll) 2993 uKeyMaskScroll = 1 << i; 2994 } 2995 XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2, 2996 &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask); 2997 XFreeModifiermap(map); 2998 2999 if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum))) 3000 { 3001 -- muNumLockAdaptionCnt; 3002 piCodes[(*puCount)++] = 0x45; 3003 piCodes[(*puCount)++] = 0x45 | 0x80; 3004 } 3005 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps))) 3006 { 3007 muCapsLockAdaptionCnt--; 3008 piCodes[(*puCount)++] = 0x3a; 3009 piCodes[(*puCount)++] = 0x3a | 0x80; 3010 /* Some keyboard layouts require shift to be pressed to break 3011 * capslock. For simplicity, only do this if shift is not 3012 * already held down. */ 3013 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 3014 { 3015 piCodes[(*puCount)++] = 0x2a; 3016 piCodes[(*puCount)++] = 0x2a | 0x80; 3017 } 3018 } 3019 3020 #elif defined (Q_WS_WIN32) 3021 3022 if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK)))) 3023 { 3024 muNumLockAdaptionCnt--; 3025 piCodes[(*puCount)++] = 0x45; 3026 piCodes[(*puCount)++] = 0x45 | 0x80; 3027 } 3028 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL)))) 3029 { 3030 muCapsLockAdaptionCnt--; 3031 piCodes[(*puCount)++] = 0x3a; 3032 piCodes[(*puCount)++] = 0x3a | 0x80; 3033 /* Some keyboard layouts require shift to be pressed to break 3034 * capslock. For simplicity, only do this if shift is not 3035 * already held down. */ 3036 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 3037 { 3038 piCodes[(*puCount)++] = 0x2a; 3039 piCodes[(*puCount)++] = 0x2a | 0x80; 3040 } 3041 } 3042 3043 #elif defined (Q_WS_MAC) 3044 3045 /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */ 3046 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock))) 3047 { 3048 muCapsLockAdaptionCnt--; 3049 piCodes[(*puCount)++] = 0x3a; 3050 piCodes[(*puCount)++] = 0x3a | 0x80; 3051 /* Some keyboard layouts require shift to be pressed to break 3052 * capslock. For simplicity, only do this if shift is not 3053 * already held down. */ 3054 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 3055 { 3056 piCodes[(*puCount)++] = 0x2a; 3057 piCodes[(*puCount)++] = 0x2a | 0x80; 3058 } 3059 } 3060 3061 #else 3062 3063 //#warning Adapt UIMachineView::fixModifierState 3064 3065 #endif 3066 } 3067 3068 void UIMachineView::scrollBy(int dx, int dy) 3069 { 3070 horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx); 3071 verticalScrollBar()->setValue(verticalScrollBar()->value() + dy); 3072 } 3073 3074 QPoint UIMachineView::viewportToContents(const QPoint &vp) const 3075 { 3076 return QPoint (vp.x() + contentsX(), vp.y() + contentsY()); 3077 } 3078 3079 void UIMachineView::updateSliders() 3080 { 3081 QSize p = viewport()->size(); 3082 QSize m = maximumViewportSize(); 3083 3084 QSize v = QSize(mFrameBuf->width(), mFrameBuf->height()); 3085 /* no scroll bars needed */ 3086 if (m.expandedTo(v) == m) 3087 p = m; 3088 3089 horizontalScrollBar()->setRange(0, v.width() - p.width()); 3090 verticalScrollBar()->setRange(0, v.height() - p.height()); 3091 horizontalScrollBar()->setPageStep(p.width()); 3092 verticalScrollBar()->setPageStep(p.height()); 3093 } 3094 3095 #ifdef VBOX_WITH_VIDEOHWACCEL 3096 void UIMachineView::scrollContentsBy (int dx, int dy) 3097 { 3098 if (mFrameBuf) 3099 { 3100 mFrameBuf->viewportScrolled(dx, dy); 3101 } 3102 QAbstractScrollArea::scrollContentsBy (dx, dy); 3103 } 3104 #endif 3105 3106 #if defined(Q_WS_MAC) 3107 void UIMachineView::updateDockIcon() 3108 { 3109 if (mDockIconEnabled) 3110 { 3111 if (!mPausedShot.isNull()) 3112 { 3113 CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot); 3114 /* Use the pause image as background */ 3115 mDockIconPreview->updateDockPreview (pauseImg); 3116 CGImageRelease (pauseImg); 3117 } 3118 else 3119 { 3120 # if defined (VBOX_GUI_USE_QUARTZ2D) 3121 if (mode == VBoxDefs::Quartz2DMode) 3122 { 3123 /* If the render mode is Quartz2D we could use the CGImageRef 3124 * of the framebuffer for the dock icon creation. This saves 3125 * some conversion time. */ 3126 mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef()); 3127 } 3128 else 3129 # endif 3130 /* In image mode we have to create the image ref out of the 3131 * framebuffer */ 3132 mDockIconPreview->updateDockPreview (mFrameBuf); 3133 } 3134 } 3135 } 3136 3137 void UIMachineView::updateDockOverlay() 3138 { 3139 /* Only to an update to the realtime preview if this is enabled by the user 3140 * & we are in an state where the framebuffer is likely valid. Otherwise to 3141 * the overlay stuff only. */ 3142 if (mDockIconEnabled && 3143 (mLastState == KMachineState_Running || 3144 mLastState == KMachineState_Paused || 3145 mLastState == KMachineState_Teleporting || 3146 mLastState == KMachineState_LiveSnapshotting || 3147 mLastState == KMachineState_Restoring || 3148 mLastState == KMachineState_TeleportingPausedVM || 3149 mLastState == KMachineState_TeleportingIn || 3150 mLastState == KMachineState_Saving)) 3151 updateDockIcon(); 3152 else 3153 mDockIconPreview->updateDockOverlay(); 3154 } 3155 3156 void UIMachineView::setMouseCoalescingEnabled (bool aOn) 3157 { 3158 /* Enable mouse event compression if we leave the VM view. This 3159 is necessary for having smooth resizing of the VM/other 3160 windows. 3161 Disable mouse event compression if we enter the VM view. So 3162 all mouse events are registered in the VM. Only do this if 3163 the keyboard/mouse is grabbed (this is when we have a valid 3164 event handler). */ 3165 if (aOn || mKeyboardGrabbed) 3166 ::darwinSetMouseCoalescingEnabled (aOn); 3167 } 3168 #endif /* Q_WS_MAC */ 3169 3170 void UIMachineView::onStateChange(KMachineState state) 3338 3171 { 3339 3172 switch (state) … … 3353 3186 */ 3354 3187 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32); 3355 CDisplay dsp = m Console.GetDisplay();3188 CDisplay dsp = m_console.GetDisplay(); 3356 3189 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 3357 3190 /* … … 3391 3224 * the viewport through IFramebuffer::NotifyUpdate) 3392 3225 */ 3393 CDisplay dsp = m Console.GetDisplay();3226 CDisplay dsp = m_console.GetDisplay(); 3394 3227 dsp.InvalidateAndUpdate(); 3395 3228 } … … 3407 3240 } 3408 3241 3409 void VBoxConsoleView::doRefresh() 3410 { 3411 viewport()->repaint(); 3412 } 3413 3414 void VBoxConsoleView::resizeEvent (QResizeEvent *) 3415 { 3416 updateSliders(); 3417 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 3418 QRect r = viewport()->geometry(); 3419 // printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height()); 3420 PostBoundsChanged (r); 3421 #endif /* Q_WS_MAC */ 3422 } 3423 3424 void VBoxConsoleView::moveEvent (QMoveEvent *) 3425 { 3426 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 3427 QRect r = viewport()->geometry(); 3428 // printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height()); 3429 PostBoundsChanged (r); 3430 #endif /* Q_WS_MAC */ 3431 } 3432 3433 void VBoxConsoleView::paintEvent (QPaintEvent *pe) 3434 { 3435 if (mPausedShot.isNull()) 3436 { 3437 /* delegate the paint function to the VBoxFrameBuffer interface */ 3438 if (mFrameBuf) 3439 mFrameBuf->paintEvent (pe); 3440 #ifdef Q_WS_MAC 3441 /* Update the dock icon if we are in the running state */ 3442 if (isRunning()) 3443 updateDockIcon(); 3444 #endif 3445 return; 3446 } 3447 3448 #ifdef VBOX_GUI_USE_QUARTZ2D 3449 if (mode == VBoxDefs::Quartz2DMode && mFrameBuf) 3450 { 3451 mFrameBuf->paintEvent (pe); 3452 updateDockIcon(); 3453 } 3454 else 3455 #endif 3456 { 3457 /* we have a snapshot for the paused state */ 3458 QRect r = pe->rect().intersect (viewport()->rect()); 3459 /* We have to disable paint on screen if we are using the regular painter */ 3460 bool paintOnScreen = viewport()->testAttribute (Qt::WA_PaintOnScreen); 3461 viewport()->setAttribute (Qt::WA_PaintOnScreen, false); 3462 QPainter pnt (viewport()); 3463 pnt.drawPixmap (r.x(), r.y(), mPausedShot, 3464 r.x() + contentsX(), r.y() + contentsY(), 3465 r.width(), r.height()); 3466 /* Restore the attribute to its previous state */ 3467 viewport()->setAttribute (Qt::WA_PaintOnScreen, paintOnScreen); 3468 #ifdef Q_WS_MAC 3469 updateDockIcon(); 3470 #endif 3471 } 3472 3473 } 3474 3475 /** 3476 * Captures the keyboard. When captured, no keyboard input reaches the host 3477 * system (including most system combinations like Alt-Tab). 3478 * 3479 * @param aCapture true to capture, false to uncapture. 3480 * @param aEmitSignal Whether to emit keyboardStateChanged() or not. 3481 */ 3482 void VBoxConsoleView::captureKbd (bool aCapture, bool aEmitSignal /* = true */) 3483 { 3484 AssertMsg (mAttached, ("Console must be attached")); 3485 3486 if (mKbdCaptured == aCapture) 3242 void UIMachineView::captureKbd(bool aCapture, bool aEmitSignal /* = true */) 3243 { 3244 //AssertMsg(m_bIsAttached, ("Console must be attached")); 3245 3246 if (m_bIsKeyboardCaptured == aCapture) 3487 3247 return; 3488 3248 … … 3497 3257 /**/ 3498 3258 #elif defined (Q_WS_X11) 3499 if (aCapture) 3500 XGrabKey (QX11Info::display(), AnyKey, AnyModifier, 3501 window()->winId(), False, 3502 GrabModeAsync, GrabModeAsync); 3503 else 3504 XUngrabKey (QX11Info::display(), AnyKey, AnyModifier, 3505 window()->winId()); 3259 if (aCapture) 3260 XGrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId(), False, GrabModeAsync, GrabModeAsync); 3261 else 3262 XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId()); 3506 3263 #elif defined (Q_WS_MAC) 3507 3264 if (aCapture) 3508 3265 { 3509 ::DarwinDisableGlobalHotKeys 3266 ::DarwinDisableGlobalHotKeys(true); 3510 3267 grabKeyboard(); 3511 3268 } 3512 3269 else 3513 3270 { 3514 ::DarwinDisableGlobalHotKeys 3271 ::DarwinDisableGlobalHotKeys(false); 3515 3272 releaseKeyboard(); 3516 3273 } … … 3522 3279 #endif 3523 3280 3524 m KbdCaptured = aCapture;3281 m_bIsKeyboardCaptured = aCapture; 3525 3282 3526 3283 if (aEmitSignal) … … 3528 3285 } 3529 3286 3530 /** 3531 * Captures the host mouse pointer. When captured, the mouse pointer is 3532 * unavailable to the host applications. 3533 * 3534 * @param aCapture true to capture, false to uncapture. 3535 * @param aEmitSignal Whether to emit mouseStateChanged() or not. 3536 */ 3537 void VBoxConsoleView::captureMouse (bool aCapture, bool aEmitSignal /* = true */) 3538 { 3539 AssertMsg (mAttached, ("Console must be attached")); 3540 3541 if (mMouseCaptured == aCapture) 3287 void UIMachineView::captureMouse(bool aCapture, bool aEmitSignal /* = true */) 3288 { 3289 //AssertMsg (m_bIsAttached, ("Console must be attached")); 3290 3291 if (m_bIsMouseCaptured == aCapture) 3542 3292 return; 3543 3293 … … 3568 3318 #endif 3569 3319 /* release mouse buttons */ 3570 CMouse mouse = m Console.GetMouse();3320 CMouse mouse = m_console.GetMouse(); 3571 3321 mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0); 3572 3322 } 3573 3323 3574 m MouseCaptured = aCapture;3324 m_bIsMouseCaptured = aCapture; 3575 3325 3576 3326 updateMouseClipping(); … … 3580 3330 } 3581 3331 3582 /** 3583 * Searches for a menu item with a given hot key (shortcut). If the item 3584 * is found, activates it and returns true. Otherwise returns false. 3585 */ 3586 bool VBoxConsoleView::processHotKey (const QKeySequence &aKey, 3587 const QList <QAction*> &aData) 3332 bool UIMachineView::processHotKey(const QKeySequence &aKey, const QList <QAction*> &aData) 3588 3333 { 3589 3334 foreach (QAction *pAction, aData) … … 3592 3337 { 3593 3338 /* Process recursively for each sub-menu */ 3594 if (processHotKey 3339 if (processHotKey(aKey, menu->actions())) 3595 3340 return true; 3596 3341 } 3597 3342 else 3598 3343 { 3599 QString hotkey = VBoxGlobal::extractKeyFromActionText 3344 QString hotkey = VBoxGlobal::extractKeyFromActionText(pAction->text()); 3600 3345 if (pAction->isEnabled() && !hotkey.isEmpty()) 3601 3346 { 3602 if (aKey.matches 3347 if (aKey.matches(QKeySequence (hotkey)) == QKeySequence::ExactMatch) 3603 3348 { 3604 3349 /* We asynchronously post a special event instead of calling … … 3609 3354 * menu data posted along with the event will remain valid in 3610 3355 * the event handler, at least until the main window is closed. */ 3611 QApplication::postEvent (this, new ActivateMenuEvent(pAction));3356 QApplication::postEvent(this, new ActivateMenuEvent(pAction)); 3612 3357 return true; 3613 3358 } … … 3619 3364 } 3620 3365 3621 /** 3622 * Send the KEY BREAK code to the VM for all currently pressed keys. 3623 * 3624 * @param aReleaseHostKey @c true to set the host key state to unpressed. 3625 */ 3626 void VBoxConsoleView::releaseAllPressedKeys (bool aReleaseHostKey /* = true*/) 3627 { 3628 AssertMsg (mAttached, ("Console must be attached")); 3629 3630 CKeyboard keyboard = mConsole.GetKeyboard(); 3366 void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */) 3367 { 3368 //AssertMsg(m_bIsAttached, ("Console must be attached")); 3369 3370 CKeyboard keyboard = m_console.GetKeyboard(); 3631 3371 bool fSentRESEND = false; 3632 3372 … … 3637 3377 * effect :), but at least it works with NT and W2k guests. */ 3638 3378 3639 /// @todo Sending 0xFE is responsible for the warning3640 //3641 // ``atkbd.c: Spurious NAK on isa0060/serio0. Some program might3642 // be trying access hardware directly''3643 //3644 // on Linux guests (#1944). It might also be responsible for #1949. Don't3645 // send this command unless we really have to release any key modifier.3646 // --frank3647 3648 3379 for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++) 3649 3380 { 3650 if (mPressedKeys 3381 if (mPressedKeys[i] & IsKeyPressed) 3651 3382 { 3652 3383 if (!fSentRESEND) … … 3655 3386 fSentRESEND = true; 3656 3387 } 3657 keyboard.PutScancode 3658 } 3659 else if (mPressedKeys 3388 keyboard.PutScancode(i | 0x80); 3389 } 3390 else if (mPressedKeys[i] & IsExtKeyPressed) 3660 3391 { 3661 3392 if (!fSentRESEND) 3662 3393 { 3663 keyboard.PutScancode 3394 keyboard.PutScancode(0xFE); 3664 3395 fSentRESEND = true; 3665 3396 } 3666 QVector <LONG> codes 3397 QVector <LONG> codes(2); 3667 3398 codes[0] = 0xE0; 3668 3399 codes[1] = i | 0x80; 3669 keyboard.PutScancodes 3670 } 3671 mPressedKeys 3400 keyboard.PutScancodes(codes); 3401 } 3402 mPressedKeys[i] = 0; 3672 3403 } 3673 3404 3674 3405 if (aReleaseHostKey) 3675 m IsHostkeyPressed = false;3406 m_bIsHostkeyPressed = false; 3676 3407 3677 3408 #ifdef Q_WS_MAC … … 3679 3410 mDarwinKeyModifiers &= 3680 3411 alphaLock | kEventKeyModifierNumLockMask | 3681 (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask ( gs.hostKey()));3412 (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey())); 3682 3413 #endif 3683 3414 … … 3685 3416 } 3686 3417 3687 void VBoxConsoleView::saveKeyStates()3688 { 3689 ::memcpy (mPressedKeysCopy, mPressedKeys, sizeof(mPressedKeys));3690 } 3691 3692 void VBoxConsoleView::sendChangedKeyStates()3693 { 3694 AssertMsg (mAttached, ("Console must be attached"));3695 3696 QVector <LONG> codes 3697 CKeyboard keyboard = m Console.GetKeyboard();3698 for (uint i = 0; i < SIZEOF_ARRAY 3699 { 3700 uint8_t os = mPressedKeysCopy 3701 uint8_t ns = mPressedKeys 3418 void UIMachineView::saveKeyStates() 3419 { 3420 ::memcpy(mPressedKeysCopy, mPressedKeys, sizeof(mPressedKeys)); 3421 } 3422 3423 void UIMachineView::sendChangedKeyStates() 3424 { 3425 //AssertMsg(m_bIsAttached, ("Console must be attached")); 3426 3427 QVector <LONG> codes(2); 3428 CKeyboard keyboard = m_console.GetKeyboard(); 3429 for (uint i = 0; i < SIZEOF_ARRAY(mPressedKeys); ++ i) 3430 { 3431 uint8_t os = mPressedKeysCopy[i]; 3432 uint8_t ns = mPressedKeys[i]; 3702 3433 if ((os & IsKeyPressed) != (ns & IsKeyPressed)) 3703 3434 { 3704 codes 3435 codes[0] = i; 3705 3436 if (!(ns & IsKeyPressed)) 3706 3437 codes[0] |= 0x80; 3707 keyboard.PutScancode 3438 keyboard.PutScancode(codes[0]); 3708 3439 } 3709 3440 else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed)) 3710 3441 { 3711 codes 3712 codes 3442 codes[0] = 0xE0; 3443 codes[1] = i; 3713 3444 if (!(ns & IsExtKeyPressed)) 3714 codes 3715 keyboard.PutScancodes 3716 } 3717 } 3718 } 3719 3720 void VBoxConsoleView::updateMouseClipping()3721 { 3722 AssertMsg (mAttached, ("Console must be attached"));3723 3724 if (m MouseCaptured)3725 { 3726 viewport()->setCursor (QCursor(Qt::BlankCursor));3445 codes[1] |= 0x80; 3446 keyboard.PutScancodes(codes); 3447 } 3448 } 3449 } 3450 3451 void UIMachineView::updateMouseClipping() 3452 { 3453 //AssertMsg(m_bIsAttached, ("Console must be attached")); 3454 3455 if (m_bIsMouseCaptured) 3456 { 3457 viewport()->setCursor(QCursor(Qt::BlankCursor)); 3727 3458 #ifdef Q_WS_WIN32 3728 3459 QRect r = viewport()->rect(); 3729 r.moveTopLeft (viewport()->mapToGlobal(QPoint (0, 0)));3460 r.moveTopLeft(viewport()->mapToGlobal(QPoint (0, 0))); 3730 3461 RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 }; 3731 ::ClipCursor 3462 ::ClipCursor(&rect); 3732 3463 #endif 3733 3464 } … … 3735 3466 { 3736 3467 #ifdef Q_WS_WIN32 3737 ::ClipCursor 3468 ::ClipCursor(NULL); 3738 3469 #endif 3739 3470 /* return the cursor to where it was when we captured it and show it */ 3740 QCursor::setPos 3471 QCursor::setPos(mCapturedPos); 3741 3472 viewport()->unsetCursor(); 3742 3473 } 3743 3474 } 3744 3475 3745 void VBoxConsoleView::setPointerShape (MousePointerChangeEvent *me)3746 { 3747 if ( me->shapeData() != NULL)3476 void UIMachineView::setPointerShape(MousePointerChangeEvent *pEvent) 3477 { 3478 if (pEvent->shapeData() != NULL) 3748 3479 { 3749 3480 bool ok = false; 3750 3481 3751 const uchar *srcAndMaskPtr = me->shapeData();3752 uint andMaskSize = ( me->width() + 7) / 8 * me->height();3753 const uchar *srcShapePtr = me->shapeData() + ((andMaskSize + 3) & ~3);3754 uint srcShapePtrScan = me->width() * 4;3482 const uchar *srcAndMaskPtr = pEvent->shapeData(); 3483 uint andMaskSize = (pEvent->width() + 7) / 8 * pEvent->height(); 3484 const uchar *srcShapePtr = pEvent->shapeData() + ((andMaskSize + 3) & ~3); 3485 uint srcShapePtrScan = pEvent->width() * 4; 3755 3486 3756 3487 #if defined (Q_WS_WIN) … … 3760 3491 void *lpBits; 3761 3492 3762 ::ZeroMemory 3763 bi.bV5Size = sizeof 3764 bi.bV5Width = me->width();3765 bi.bV5Height = - (LONG) me->height();3493 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER)); 3494 bi.bV5Size = sizeof(BITMAPV5HEADER); 3495 bi.bV5Width = pEvent->width(); 3496 bi.bV5Height = - (LONG)pEvent->height(); 3766 3497 bi.bV5Planes = 1; 3767 3498 bi.bV5BitCount = 32; 3768 3499 bi.bV5Compression = BI_BITFIELDS; 3769 // specifiy a supported 32 BPP alpha format for Windows XP3770 3500 bi.bV5RedMask = 0x00FF0000; 3771 3501 bi.bV5GreenMask = 0x0000FF00; 3772 3502 bi.bV5BlueMask = 0x000000FF; 3773 if ( me->hasAlpha())3503 if (pEvent->hasAlpha()) 3774 3504 bi.bV5AlphaMask = 0xFF000000; 3775 3505 else 3776 3506 bi.bV5AlphaMask = 0; 3777 3507 3778 HDC hdc = GetDC 3508 HDC hdc = GetDC(NULL); 3779 3509 3780 3510 // create the DIB section with an alpha channel 3781 hBitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS, 3782 (void **) &lpBits, NULL, (DWORD) 0); 3783 3784 ReleaseDC (NULL, hdc); 3511 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0); 3512 3513 ReleaseDC(NULL, hdc); 3785 3514 3786 3515 HBITMAP hMonoBitmap = NULL; 3787 if ( me->hasAlpha())3516 if (pEvent->hasAlpha()) 3788 3517 { 3789 3518 // create an empty mask bitmap 3790 hMonoBitmap = CreateBitmap (me->width(), me->height(), 1, 1, NULL);3519 hMonoBitmap = CreateBitmap(pEvent->width(), pEvent->height(), 1, 1, NULL); 3791 3520 } 3792 3521 else … … 3796 3525 3797 3526 /* Width in bytes of the original AND mask scan line. */ 3798 uint32_t cbAndMaskScan = ( me->width() + 7) / 8;3527 uint32_t cbAndMaskScan = (pEvent->width() + 7) / 8; 3799 3528 3800 3529 if (cbAndMaskScan & 1) … … 3803 3532 3804 3533 /* Allocate memory for aligned AND mask. */ 3805 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ ((cbAndMaskScan + 1) * me->height());3534 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * pEvent->height()); 3806 3535 3807 3536 Assert(pu8AndMaskWordAligned); … … 3810 3539 { 3811 3540 /* According to MSDN the padding bits must be 0. 3812 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. 3813 */ 3814 uint32_t u32PaddingBits = cbAndMaskScan * 8 - me->width(); 3541 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */ 3542 uint32_t u32PaddingBits = cbAndMaskScan * 8 - pEvent->width(); 3815 3543 Assert(u32PaddingBits < 8); 3816 3544 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 3817 3545 3818 3546 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 3819 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, me->width(), cbAndMaskScan));3547 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, pEvent->width(), cbAndMaskScan)); 3820 3548 3821 3549 uint8_t *src = (uint8_t *)srcAndMaskPtr; … … 3823 3551 3824 3552 unsigned i; 3825 for (i = 0; i < me->height(); i++)3553 for (i = 0; i < pEvent->height(); i++) 3826 3554 { 3827 memcpy 3555 memcpy(dst, src, cbAndMaskScan); 3828 3556 3829 3557 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; … … 3836 3564 3837 3565 /* create the AND mask bitmap */ 3838 hMonoBitmap = ::CreateBitmap (me->width(), me->height(), 1, 1,3839 3566 hMonoBitmap = ::CreateBitmap(pEvent->width(), pEvent->height(), 1, 1, 3567 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 3840 3568 3841 3569 if (pu8AndMaskWordAligned) 3842 3570 { 3843 RTMemTmpFree 3844 } 3845 } 3846 3847 Assert 3848 Assert 3571 RTMemTmpFree(pu8AndMaskWordAligned); 3572 } 3573 } 3574 3575 Assert(hBitmap); 3576 Assert(hMonoBitmap); 3849 3577 if (hBitmap && hMonoBitmap) 3850 3578 { 3851 3579 DWORD *dstShapePtr = (DWORD *) lpBits; 3852 3580 3853 for (uint y = 0; y < me->height(); y ++)3854 { 3855 memcpy 3581 for (uint y = 0; y < pEvent->height(); y ++) 3582 { 3583 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan); 3856 3584 srcShapePtr += srcShapePtrScan; 3857 dstShapePtr += me->width();3585 dstShapePtr += pEvent->width(); 3858 3586 } 3859 3587 3860 3588 ICONINFO ii; 3861 3589 ii.fIcon = FALSE; 3862 ii.xHotspot = me->xHot();3863 ii.yHotspot = me->yHot();3590 ii.xHotspot = pEvent->xHot(); 3591 ii.yHotspot = pEvent->yHot(); 3864 3592 ii.hbmMask = hMonoBitmap; 3865 3593 ii.hbmColor = hBitmap; 3866 3594 3867 HCURSOR hAlphaCursor = CreateIconIndirect 3868 Assert 3595 HCURSOR hAlphaCursor = CreateIconIndirect(&ii); 3596 Assert(hAlphaCursor); 3869 3597 if (hAlphaCursor) 3870 3598 { 3871 viewport()->setCursor (QCursor(hAlphaCursor));3599 viewport()->setCursor(QCursor(hAlphaCursor)); 3872 3600 ok = true; 3873 3601 if (mAlphaCursor) 3874 DestroyIcon 3602 DestroyIcon(mAlphaCursor); 3875 3603 mAlphaCursor = hAlphaCursor; 3876 3604 } … … 3878 3606 3879 3607 if (hMonoBitmap) 3880 DeleteObject 3608 DeleteObject(hMonoBitmap); 3881 3609 if (hBitmap) 3882 DeleteObject 3610 DeleteObject(hBitmap); 3883 3611 3884 3612 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 3885 3613 3886 XcursorImage *img = XcursorImageCreate ( me->width(), me->height());3614 XcursorImage *img = XcursorImageCreate (pEvent->width(), pEvent->height()); 3887 3615 Assert (img); 3888 3616 if (img) 3889 3617 { 3890 img->xhot = me->xHot();3891 img->yhot = me->yHot();3618 img->xhot = pEvent->xHot(); 3619 img->yhot = pEvent->yHot(); 3892 3620 3893 3621 XcursorPixel *dstShapePtr = img->pixels; 3894 3622 3895 for (uint y = 0; y < me->height(); y ++)3623 for (uint y = 0; y < pEvent->height(); y ++) 3896 3624 { 3897 3625 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 3898 3626 3899 if (! me->hasAlpha())3627 if (!pEvent->hasAlpha()) 3900 3628 { 3901 3629 /* convert AND mask to the alpha channel */ 3902 3630 uchar byte = 0; 3903 for (uint x = 0; x < me->width(); x ++)3631 for (uint x = 0; x < pEvent->width(); x ++) 3904 3632 { 3905 3633 if (!(x % 8)) … … 3925 3653 3926 3654 srcShapePtr += srcShapePtrScan; 3927 dstShapePtr += me->width();3655 dstShapePtr += pEvent->width(); 3928 3656 } 3929 3657 … … 3942 3670 3943 3671 /* Create a ARGB image out of the shape data. */ 3944 QImage image ( me->width(), me->height(), QImage::Format_ARGB32);3672 QImage image (pEvent->width(), pEvent->height(), QImage::Format_ARGB32); 3945 3673 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 3946 unsigned cbSrcMaskLine = RT_ALIGN ( me->width(), 8) / 8;3947 for (unsigned int y = 0; y < me->height(); ++y)3948 { 3949 for (unsigned int x = 0; x < me->width(); ++x)3950 { 3951 unsigned int color = ((unsigned int*)srcShapePtr)[y* me->width()+x];3674 unsigned cbSrcMaskLine = RT_ALIGN (pEvent->width(), 8) / 8; 3675 for (unsigned int y = 0; y < pEvent->height(); ++y) 3676 { 3677 for (unsigned int x = 0; x < pEvent->width(); ++x) 3678 { 3679 unsigned int color = ((unsigned int*)srcShapePtr)[y*pEvent->width()+x]; 3952 3680 /* If the alpha channel isn't in the shape data, we have to 3953 3681 * create them from the and-mask. This is a bit field where 1 3954 3682 * represent transparency & 0 opaque respectively. */ 3955 if (! me->hasAlpha())3683 if (!pEvent->hasAlpha()) 3956 3684 { 3957 3685 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) … … 3973 3701 } 3974 3702 /* Set the new cursor */ 3975 QCursor cursor (QPixmap::fromImage (image), 3976 me->xHot(), me->yHot()); 3703 QCursor cursor (QPixmap::fromImage (image), pEvent->xHot(), pEvent->yHot()); 3977 3704 viewport()->setCursor (cursor); 3978 3705 ok = true; … … 3984 3711 3985 3712 #endif 3713 3986 3714 if (ok) 3987 3715 mLastCursor = viewport()->cursor(); … … 3991 3719 else 3992 3720 { 3993 /* 3994 * We did not get any shape data 3995 */ 3996 if (me->isVisible()) 3997 { 3998 viewport()->setCursor (mLastCursor); 3721 if (pEvent->isVisible()) 3722 { 3723 viewport()->setCursor(mLastCursor); 3999 3724 } 4000 3725 else 4001 3726 { 4002 viewport()->setCursor (Qt::BlankCursor); 4003 } 4004 } 4005 mHideHostPointer = !me->isVisible(); 4006 } 4007 4008 inline QRgb qRgbIntensity (QRgb rgb, int mul, int div) 4009 { 4010 int r = qRed (rgb); 4011 int g = qGreen (rgb); 4012 int b = qBlue (rgb); 4013 return qRgb (mul * r / div, mul * g / div, mul * b / div); 4014 } 4015 4016 /* static */ 4017 void VBoxConsoleView::dimImage (QImage &img) 4018 { 4019 for (int y = 0; y < img.height(); y ++) { 4020 if (y % 2) { 4021 if (img.depth() == 32) { 4022 for (int x = 0; x < img.width(); x ++) { 4023 int gray = qGray (img.pixel (x, y)) / 2; 4024 img.setPixel (x, y, qRgb (gray, gray, gray)); 4025 // img.setPixel (x, y, qRgbIntensity (img.pixel (x, y), 1, 2)); 4026 } 4027 } else { 4028 ::memset (img.scanLine (y), 0, img.bytesPerLine()); 4029 } 4030 } else { 4031 if (img.depth() == 32) { 4032 for (int x = 0; x < img.width(); x ++) { 4033 int gray = (2 * qGray (img.pixel (x, y))) / 3; 4034 img.setPixel (x, y, qRgb (gray, gray, gray)); 4035 // img.setPixel (x, y, qRgbIntensity (img.pixel(x, y), 2, 3)); 4036 } 4037 } 4038 } 4039 } 4040 } 4041 4042 void VBoxConsoleView::doResizeHint (const QSize &aToSize) 4043 { 4044 if (mGuestSupportsGraphics && mAutoresizeGuest) 4045 { 4046 /* If this slot is invoked directly then use the passed size 4047 * otherwise get the available size for the guest display. 4048 * We assume here that the centralWidget() contains this view only 4049 * and gives it all available space. */ 4050 QSize sz (aToSize.isValid() ? aToSize : mMainWnd->centralWidget()->size()); 4051 if (!aToSize.isValid()) 4052 sz -= QSize (frameWidth() * 2, frameWidth() * 2); 4053 /* Do not send out useless hints. */ 4054 if ((sz.width() == mStoredConsoleSize.width()) && 4055 (sz.height() == mStoredConsoleSize.height())) 4056 return; 4057 /* We only actually send the hint if 4058 * 1) the autoresize property is set to true and 4059 * 2) either an explicit new size was given (e.g. if the request 4060 * was triggered directly by a console resize event) or if no 4061 * explicit size was specified but a resize is flagged as being 4062 * needed (e.g. the autoresize was just enabled and the console 4063 * was resized while it was disabled). */ 4064 if (mAutoresizeGuest && 4065 (aToSize.isValid() || mDoResize)) 4066 { 4067 LogFlowFunc (("Will suggest %d x %d\n", sz.width(), sz.height())); 4068 4069 /* Remember the new size. */ 4070 storeConsoleSize (sz.width(), sz.height()); 4071 4072 mConsole.GetDisplay().SetVideoModeHint (sz.width(), sz.height(), 0, 0); 4073 } 4074 /* we have resized now... */ 4075 mDoResize = false; 4076 } 4077 } 4078 4079 4080 /* If the desktop geometry is set automatically, this will update it. */ 4081 void VBoxConsoleView::doResizeDesktop (int) 4082 { 4083 calculateDesktopGeometry(); 4084 } 4085 4086 /** 4087 * Store the current size of the console (i.e. the viewport to the guest). 4088 * This has two purposes. One is to suppress unwanted resize events for 4089 * which the new size is the same as the stored size. The other is to expand 4090 * the maximum size to which we will let the guest resize itself. It makes 4091 * no sense to forbid guest resizes which are less than the current resolution 4092 * anyway. 4093 * 4094 * @param aWidth width of the resolution hint 4095 * @param aHeight height of the resolution hint 4096 */ 4097 void VBoxConsoleView::storeConsoleSize (int aWidth, int aHeight) 4098 { 4099 LogFlowThisFunc (("aWidth=%d, aHeight=%d\n", aWidth, aHeight)); 4100 mStoredConsoleSize = QRect (0, 0, aWidth, aHeight); 4101 } 4102 4103 /** 4104 * Do initial setup of desktop geometry restrictions on the guest framebuffer. 4105 * These determine the maximum size the guest framebuffer can take on. 4106 * 4107 * @note a hint from the host will always override these restrictions. 4108 * 4109 * @param aGeo Fixed - the guest has a fixed maximum framebuffer size 4110 * Automatic - we calculate the maximum size ourselves. The 4111 * calculations will not actually be done until 4112 * @a calculateDesktopGeometry is called, since 4113 * we don't initially have the information needed. 4114 * Any - any size is allowed 4115 * @param aWidth The maximum width for the guest screen or zero for no change 4116 * (only used for fixed geometry) 4117 * @param aHeight The maximum height for the guest screen or zero for no change 4118 * (only used for fixed geometry) 4119 */ 4120 void VBoxConsoleView::setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight) 4121 { 4122 LogFlowThisFunc (("aGeo=%s, aWidth=%d, aHeight=%d\n", 4123 (aGeo == DesktopGeo_Fixed ? "Fixed" : 4124 aGeo == DesktopGeo_Automatic ? "Automatic" : 4125 aGeo == DesktopGeo_Any ? "Any" : "Invalid"), 4126 aWidth, aHeight)); 3727 viewport()->setCursor(Qt::BlankCursor); 3728 } 3729 } 3730 mHideHostPointer = !pEvent->isVisible(); 3731 } 3732 3733 inline QRgb qRgbIntensity(QRgb rgb, int mul, int div) 3734 { 3735 int r = qRed(rgb); 3736 int g = qGreen(rgb); 3737 int b = qBlue(rgb); 3738 return qRgb(mul * r / div, mul * g / div, mul * b / div); 3739 } 3740 3741 void UIMachineView::storeConsoleSize(int aWidth, int aHeight) 3742 { 3743 LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight)); 3744 mStoredConsoleSize = QRect(0, 0, aWidth, aHeight); 3745 } 3746 3747 void UIMachineView::setMouseIntegrationLocked(bool bDisabled) 3748 { 3749 machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setChecked(false); 3750 machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setEnabled(bDisabled); 3751 } 3752 3753 void UIMachineView::setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight) 3754 { 4127 3755 switch (aGeo) 4128 3756 { … … 4130 3758 mDesktopGeo = DesktopGeo_Fixed; 4131 3759 if (aWidth != 0 && aHeight != 0) 4132 mDesktopGeometry = QRect 3760 mDesktopGeometry = QRect(0, 0, aWidth, aHeight); 4133 3761 else 4134 mDesktopGeometry = QRect 4135 storeConsoleSize 3762 mDesktopGeometry = QRect(0, 0, 0, 0); 3763 storeConsoleSize(0, 0); 4136 3764 break; 4137 3765 case DesktopGeo_Automatic: 4138 3766 mDesktopGeo = DesktopGeo_Automatic; 4139 mDesktopGeometry = QRect 4140 storeConsoleSize 3767 mDesktopGeometry = QRect(0, 0, 0, 0); 3768 storeConsoleSize(0, 0); 4141 3769 break; 4142 3770 case DesktopGeo_Any: 4143 3771 mDesktopGeo = DesktopGeo_Any; 4144 mDesktopGeometry = QRect 3772 mDesktopGeometry = QRect(0, 0, 0, 0); 4145 3773 break; 4146 3774 default: … … 4150 3778 } 4151 3779 4152 4153 /** 4154 * If we are in automatic mode, the geometry restrictions will be recalculated. 4155 * This is needed in particular on the first widget resize, as we can't 4156 * calculate them correctly before that. 4157 * 4158 * @note a hint from the host will always override these restrictions. 4159 * @note we can't do calculations on the fly when they are needed, because 4160 * they require querying the X server on X11 hosts and this must be done 4161 * from within the GUI thread, due to the single threadedness of Xlib. 4162 */ 4163 void VBoxConsoleView::calculateDesktopGeometry() 4164 { 4165 LogFlowThisFunc (("Entering\n")); 4166 /* This method should not get called until we have initially set up the */ 4167 Assert ((mDesktopGeo != DesktopGeo_Invalid)); 4168 /* If we are not doing automatic geometry calculation then there is 4169 * nothing to do. */ 4170 if (DesktopGeo_Automatic == mDesktopGeo) 4171 { 4172 /* Available geometry of the desktop. If the desktop is a single 4173 * screen, this will exclude space taken up by desktop taskbars 4174 * and things, but this is unfortunately not true for the more 4175 * complex case of a desktop spanning multiple screens. */ 4176 QRect desktop = availableGeometry(); 4177 /* The area taken up by the console window on the desktop, 4178 * including window frame, title and menu bar and whatnot. */ 4179 QRect frame = mMainWnd->frameGeometry(); 4180 /* The area taken up by the console window, minus all 4181 * decorations. */ 4182 QRect window = mMainWnd->centralWidget()->geometry(); 4183 /* To work out how big we can make the console window while still 4184 * fitting on the desktop, we calculate desktop - frame + window. 4185 * This works because the difference between frame and window 4186 * (or at least its width and height) is a constant. */ 4187 mDesktopGeometry = 4188 QRect (0, 0, desktop.width() - frame.width() + window.width(), 4189 desktop.height() - frame.height() + window.height()); 4190 LogFlowThisFunc (("Setting %d, %d\n", mDesktopGeometry.width(), 4191 mDesktopGeometry.height())); 4192 } 4193 } 4194 4195 /** 4196 * Sets the minimum size restriction depending on the auto-resize feature 4197 * state and the current rendering mode. 4198 * 4199 * Currently, the restriction is set only in SDL mode and only when the 4200 * auto-resize feature is inactive. We need to do that because we cannot 4201 * correctly draw in a scrolled window in SDL mode. 4202 * 4203 * In all other modes, or when auto-resize is in force, this function does 4204 * nothing. 4205 */ 4206 void VBoxConsoleView::maybeRestrictMinimumSize() 4207 { 4208 if (mode == VBoxDefs::SDLMode) 4209 { 4210 if (!mGuestSupportsGraphics || !mAutoresizeGuest) 4211 setMinimumSize (sizeHint()); 4212 else 4213 setMinimumSize (0, 0); 4214 } 4215 } 4216 4217 QRect VBoxConsoleView::availableGeometry() const 4218 { 4219 return mMainWnd->isWindowFullScreen() ? 3780 QRect UIMachineView::availableGeometry() 3781 { 3782 return machineWindowWrapper()->machineWindow()->isFullScreen() ? 4220 3783 QApplication::desktop()->screenGeometry(this) : 4221 3784 QApplication::desktop()->availableGeometry(this); 4222 3785 } 4223 3786 4224 int VBoxConsoleView::contentsWidth() const 4225 { 4226 return mFrameBuf->width(); 4227 } 4228 4229 int VBoxConsoleView::contentsHeight() const 4230 { 4231 return mFrameBuf->height(); 4232 } 4233 4234 void VBoxConsoleView::updateSliders() 4235 { 4236 QSize p = viewport()->size(); 4237 QSize m = maximumViewportSize(); 4238 4239 QSize v = QSize (mFrameBuf->width(), mFrameBuf->height()); 4240 /* no scroll bars needed */ 4241 if (m.expandedTo(v) == m) 4242 p = m; 4243 4244 horizontalScrollBar()->setRange(0, v.width() - p.width()); 4245 verticalScrollBar()->setRange(0, v.height() - p.height()); 4246 horizontalScrollBar()->setPageStep(p.width()); 4247 verticalScrollBar()->setPageStep(p.height()); 4248 } 4249 4250 void VBoxConsoleView::requestToResize (const QSize &aSize) 4251 { 4252 mIgnoreFrameBufferResize = true; 4253 mNormalSize = aSize; 4254 } 4255 4256 #if defined(Q_WS_MAC) 4257 4258 void VBoxConsoleView::updateDockIcon() 4259 { 4260 if (mDockIconEnabled) 4261 { 4262 if (!mPausedShot.isNull()) 4263 { 4264 CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot); 4265 /* Use the pause image as background */ 4266 mDockIconPreview->updateDockPreview (pauseImg); 4267 CGImageRelease (pauseImg); 3787 void UIMachineView::dimImage(QImage &img) 3788 { 3789 for (int y = 0; y < img.height(); ++ y) 3790 { 3791 if (y % 2) 3792 { 3793 if (img.depth() == 32) 3794 { 3795 for (int x = 0; x < img.width(); ++ x) 3796 { 3797 int gray = qGray(img.pixel (x, y)) / 2; 3798 img.setPixel(x, y, qRgb (gray, gray, gray)); 3799 } 3800 } 3801 else 3802 { 3803 ::memset(img.scanLine (y), 0, img.bytesPerLine()); 3804 } 4268 3805 } 4269 3806 else 4270 3807 { 4271 # if defined (VBOX_GUI_USE_QUARTZ2D) 4272 if (mode == VBoxDefs::Quartz2DMode) 4273 { 4274 /* If the render mode is Quartz2D we could use the CGImageRef 4275 * of the framebuffer for the dock icon creation. This saves 4276 * some conversion time. */ 4277 mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef()); 4278 } 4279 else 4280 # endif 4281 /* In image mode we have to create the image ref out of the 4282 * framebuffer */ 4283 mDockIconPreview->updateDockPreview (mFrameBuf); 4284 } 4285 } 4286 } 4287 4288 void VBoxConsoleView::updateDockOverlay() 4289 { 4290 /* Only to an update to the realtime preview if this is enabled by the user 4291 * & we are in an state where the framebuffer is likely valid. Otherwise to 4292 * the overlay stuff only. */ 4293 if (mDockIconEnabled && 4294 (mLastState == KMachineState_Running || 4295 mLastState == KMachineState_Paused || 4296 mLastState == KMachineState_Teleporting || 4297 mLastState == KMachineState_LiveSnapshotting || 4298 mLastState == KMachineState_Restoring || 4299 mLastState == KMachineState_TeleportingPausedVM || 4300 mLastState == KMachineState_TeleportingIn || 4301 mLastState == KMachineState_Saving)) 4302 updateDockIcon(); 4303 else 4304 mDockIconPreview->updateDockOverlay(); 4305 } 4306 4307 /** 4308 * Wrapper for SetMouseCoalescingEnabled(). 4309 * 4310 * Called by eventFilter() and darwinGrabKeyboardEvents(). 4311 * 4312 * @param aOn Switch it on (true) or off (false). 4313 */ 4314 void VBoxConsoleView::setMouseCoalescingEnabled (bool aOn) 4315 { 4316 /* Enable mouse event compression if we leave the VM view. This 4317 is necessary for having smooth resizing of the VM/other 4318 windows. 4319 Disable mouse event compression if we enter the VM view. So 4320 all mouse events are registered in the VM. Only do this if 4321 the keyboard/mouse is grabbed (this is when we have a valid 4322 event handler). */ 4323 if (aOn || mKeyboardGrabbed) 4324 ::darwinSetMouseCoalescingEnabled (aOn); 4325 } 4326 4327 #endif /* Q_WS_MAC */ 4328 3808 if (img.depth() == 32) 3809 { 3810 for (int x = 0; x < img.width(); ++ x) 3811 { 3812 int gray = (2 * qGray (img.pixel (x, y))) / 3; 3813 img.setPixel(x, y, qRgb (gray, gray, gray)); 3814 } 3815 } 3816 } 3817 } 3818 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleView class declaration4 * UIMachineView class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef ___VBoxConsoleView_h___ 24 #define ___VBoxConsoleView_h___ 25 23 #ifndef ___UIMachineView_h___ 24 #define ___UIMachineView_h___ 25 26 /* Local forwards */ 27 class UIFrameBuffer; 28 class UIMachineWindow; 29 class VBoxGlobalSettings; 30 class MousePointerChangeEvent; 31 32 /* Global includes */ 33 #include <QAbstractScrollArea> 34 35 /* Local includes */ 26 36 #include "COMDefs.h" 27 28 #include "VBoxDefs.h" 29 #include "VBoxGlobalSettings.h" 30 31 /* Qt includes */ 32 #include <QAbstractScrollArea> 33 #include <QScrollBar> 34 35 #if defined (Q_WS_PM) 36 #include "src/os2/VBoxHlp.h" 37 #define UM_PREACCEL_CHAR WM_USER 38 #endif 39 40 #if defined (Q_WS_MAC) 41 # include <ApplicationServices/ApplicationServices.h> 42 # ifndef QT_MAC_USE_COCOA 43 # include <Carbon/Carbon.h> 44 # endif /* !QT_MAC_USE_COCOA */ 45 #endif 46 47 class VBoxConsoleWnd; 48 class MousePointerChangeEvent; 49 class VBoxFrameBuffer; 50 class VBoxDockIconPreview; 51 52 class QPainter; 53 class QLabel; 54 class QMenuData; 55 56 class VBoxConsoleView : public QAbstractScrollArea 37 #include "UIMachineDefs.h" 38 39 class UIMachineView : public QAbstractScrollArea 57 40 { 58 Q_OBJECT 41 Q_OBJECT; 59 42 60 43 public: 61 44 62 enum { 63 MouseCaptured = 0x01, 64 MouseAbsolute = 0x02, 65 MouseAbsoluteDisabled = 0x04, 66 MouseNeedsHostCursor = 0x08, 67 KeyboardCaptured = 0x01, 68 HostKeyPressed = 0x02, 69 }; 70 71 VBoxConsoleView (VBoxConsoleWnd *mainWnd, 72 const CConsole &console, 73 VBoxDefs::RenderMode rm, 74 #ifdef VBOX_WITH_VIDEOHWACCEL 75 bool accelerate2DVideo, 76 #endif 77 QWidget *parent = 0); 78 ~VBoxConsoleView(); 79 80 QSize sizeHint() const; 81 82 void attach(); 83 void detach(); 84 void refresh() { doRefresh(); } 85 void normalizeGeometry (bool adjustPosition = false); 86 87 CConsole &console() { return mConsole; } 88 89 bool pause (bool on); 90 bool isPaused() 91 { 92 return mLastState == KMachineState_Paused 93 || mLastState == KMachineState_TeleportingPausedVM; 94 } 95 const QPixmap& pauseShot() const { return mPausedShot; } 96 97 void setMouseIntegrationEnabled (bool enabled); 98 99 bool isMouseAbsolute() const { return mMouseAbsolute; } 100 101 bool shouldHideHostPointer() const 102 { return mMouseCaptured || (mMouseAbsolute && mHideHostPointer); } 103 104 void setAutoresizeGuest (bool on); 105 106 void onFullscreenChange (bool on); 107 45 /* Factory function to create required view sub-child: */ 46 static UIMachineView* create( UIMachineWindow *pMachineWindow 47 , VBoxDefs::RenderMode renderMode 48 #ifdef VBOX_WITH_VIDEOHWACCEL 49 , bool bAccelerate2DVideo 50 #endif 51 , UIVisualStateType visualStateType); 52 53 /* Adjust view geometry: */ 54 virtual void normalizeGeometry(bool bAdjustPosition = false) = 0; 55 56 /* Public members: */ 57 // TODO: Is it needed now? 108 58 void onViewOpened(); 109 59 110 void fixModifierState (LONG *codes, uint *count); 111 112 void toggleFSMode (const QSize &aSize = QSize()); 113 114 void setIgnoreMainwndResize (bool aYes) { mIgnoreMainwndResize = aYes; } 115 void setIgnoreGuestResize (bool aYes) { mIgnoreGuestResize = aYes; } 116 117 QRect desktopGeometry(); 118 119 QRegion lastVisibleRegion() const; 120 121 bool isAutoresizeGuestActive(); 122 123 /* todo: This are some support functions for the qt4 port. Maybe we get rid 124 * of them some day. */ 125 int contentsX() const { return horizontalScrollBar()->value(); } 126 int contentsY() const { return verticalScrollBar()->value(); } 127 int contentsWidth() const; 128 int contentsHeight() const; 129 int visibleWidth() const { return horizontalScrollBar()->pageStep(); } 130 int visibleHeight() const { return verticalScrollBar()->pageStep(); } 131 void scrollBy (int dx, int dy) 132 { 133 horizontalScrollBar()->setValue (horizontalScrollBar()->value() + dx); 134 verticalScrollBar()->setValue (verticalScrollBar()->value() + dy); 135 } 136 QPoint viewportToContents ( const QPoint & vp ) const 137 { 138 return QPoint (vp.x() + contentsX(), 139 vp.y() + contentsY()); 140 } 141 void updateSliders(); 142 143 void requestToResize (const QSize &aSize); 144 145 #ifdef VBOX_WITH_VIDEOHWACCEL 146 void scrollContentsBy (int dx, int dy); 147 #endif 148 149 #if defined(Q_WS_MAC) 150 void updateDockIcon(); 151 void updateDockOverlay(); 152 void setDockIconEnabled (bool aOn) { mDockIconEnabled = aOn; }; 153 void setMouseCoalescingEnabled (bool aOn); 154 #endif 60 /* Public getters: */ 61 int contentsX() const; 62 int contentsY() const; 63 QRect desktopGeometry() const; 64 bool isMouseAbsolute() const { return m_bIsMouseAbsolute; } 65 66 /* Public setters: */ 67 void setIgnoreGuestResize(bool bIgnore); 68 void setMouseIntegrationEnabled(bool bEnabled); 155 69 156 70 signals: 157 71 158 void keyboardStateChanged (int state);159 void mouseStateChanged (int state);160 void machineStateChanged 161 void additionsStateChanged (const QString &, bool, bool, bool);162 void mediaDriveChanged (VBoxDefs::MediumType aType);72 void keyboardStateChanged(int iState); 73 void mouseStateChanged(int iState); 74 void machineStateChanged(KMachineState state); 75 void additionsStateChanged(const QString &strVersion, bool bIsActive, bool bIsGraphicSupported, bool bIsSeamlessSupported); 76 void mediaDriveChanged(VBoxDefs::MediumType type); 163 77 void networkStateChange(); 164 78 void usbStateChange(); … … 166 80 void resizeHintDone(); 167 81 82 protected slots: 83 84 virtual void doResizeHint(const QSize &aSize = QSize()) = 0; 85 168 86 protected: 169 87 170 // events 171 bool event (QEvent *e); 172 bool eventFilter (QObject *watched, QEvent *e); 173 88 UIMachineView( UIMachineWindow *pMachineWindow 89 , VBoxDefs::RenderMode renderMode 90 #ifdef VBOX_WITH_VIDEOHWACCEL 91 , bool bAccelerate2DVideo 92 #endif 93 ); 94 virtual ~UIMachineView(); 95 96 /* Protected members: */ 97 void calculateDesktopGeometry(); 98 99 /* Protected getters: */ 100 UIMachineWindow* machineWindowWrapper() { return m_pMachineWindow; } 101 QSize sizeHint() const; 102 103 /* Protected variables: */ 104 VBoxDefs::RenderMode mode; 105 bool m_bIsGuestSupportsGraphics : 1; 106 107 private slots: 108 109 #ifdef Q_WS_MAC 110 /* Dock icon update handler */ 111 void sltChangeDockIconUpdate(const VBoxChangeDockIconUpdateEvent &event); 112 113 # ifdef QT_MAC_USE_COCOA 114 /* Presentation mode handler */ 115 void sltChangePresentationMode(const VBoxChangePresentationModeEvent &event); 116 # endif 117 #endif 118 119 private: 120 121 /* Private getters: */ 122 int contentsWidth() const; 123 int contentsHeight() const; 124 int visibleWidth() const; 125 int visibleHeight() const; 126 const QPixmap& pauseShot() const { return mPausedShot; } 127 bool shouldHideHostPointer() const { return m_bIsMouseCaptured || (m_bIsMouseAbsolute && mHideHostPointer); } 128 bool isRunning() { return mLastState == KMachineState_Running || mLastState == KMachineState_Teleporting || mLastState == KMachineState_LiveSnapshotting; } 129 CConsole &console() { return m_console; } 130 131 /* Event processors: */ 132 bool event(QEvent *pEvent); 133 bool eventFilter(QObject *pWatched, QEvent *pEvent); 174 134 #if defined(Q_WS_WIN32) 175 bool winLowKeyboardEvent 135 bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event); 176 136 bool winEvent (MSG *aMsg, long *aResult); 177 137 #elif defined(Q_WS_PM) … … 183 143 void darwinGrabKeyboardEvents (bool fGrab); 184 144 #endif 185 186 private: 187 188 /** Flags for keyEvent(). */ 189 enum { 190 KeyExtended = 0x01, 191 KeyPressed = 0x02, 192 KeyPause = 0x04, 193 KeyPrint = 0x08, 194 }; 195 196 void focusEvent (bool aHasFocus, bool aReleaseHostKey = true); 197 bool keyEvent (int aKey, uint8_t aScan, int aFlags, 198 wchar_t *aUniKey = NULL); 199 bool mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos, 200 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 201 int aWheelDelta, Qt::Orientation aWheelDir); 202 145 #if defined (Q_WS_WIN32) 146 static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); 147 #elif defined (Q_WS_MAC) 148 # if defined (QT_MAC_USE_COCOA) 149 static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); 150 # elif !defined (VBOX_WITH_HACKED_QT) 151 static pascal OSStatus darwinEventHandlerProc(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); 152 # else /* VBOX_WITH_HACKED_QT */ 153 static bool macEventFilter(EventRef inEvent, void *inUserData); 154 # endif /* VBOX_WITH_HACKED_QT */ 155 #endif 156 157 /* Flags for keyEvent() */ 158 enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 }; 203 159 void emitKeyboardStateChanged() 204 160 { 205 emit keyboardStateChanged ( 206 (mKbdCaptured ? KeyboardCaptured : 0) | 207 (mIsHostkeyPressed ? HostKeyPressed : 0)); 161 emit keyboardStateChanged((m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) | 162 (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0)); 208 163 } 209 210 void emitMouseStateChanged(){211 emit mouseStateChanged ((mMouseCaptured ?MouseCaptured : 0) |212 (mMouseAbsolute ?MouseAbsolute : 0) |213 (!mMouseIntegration ?MouseAbsoluteDisabled : 0));164 void emitMouseStateChanged() 165 { 166 emit mouseStateChanged((m_bIsMouseCaptured ? UIMouseStateType_MouseCaptured : 0) | 167 (m_bIsMouseAbsolute ? UIMouseStateType_MouseAbsolute : 0) | 168 (!m_bIsMouseIntegrated ? UIMouseStateType_MouseAbsoluteDisabled : 0)); 214 169 } 215 170 216 // IConsoleCallback event handlers 217 void onStateChange (KMachineState state); 218 219 void doRefresh(); 220 221 void resizeEvent (QResizeEvent *); 222 void moveEvent (QMoveEvent *); 223 void paintEvent (QPaintEvent *); 224 225 void captureKbd (bool aCapture, bool aEmitSignal = true); 226 void captureMouse (bool aCapture, bool aEmitSignal = true); 227 228 bool processHotKey (const QKeySequence &key, const QList<QAction*>& data); 229 void updateModifiers (bool fNumLock, bool fCapsLock, bool fScrollLock); 230 231 void releaseAllPressedKeys (bool aReleaseHostKey = true); 171 void focusEvent(bool aHasFocus, bool aReleaseHostKey = true); 172 bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL); 173 bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos, 174 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 175 int aWheelDelta, Qt::Orientation aWheelDir); 176 void resizeEvent(QResizeEvent *pEvent); 177 void moveEvent(QMoveEvent *pEvent); 178 void paintEvent(QPaintEvent *pEvent); 179 180 /* Private members: */ 181 void fixModifierState(LONG *piCodes, uint *puCount); 182 void scrollBy(int dx, int dy); 183 QPoint viewportToContents(const QPoint &vp) const; 184 void updateSliders(); 185 #ifdef VBOX_WITH_VIDEOHWACCEL 186 void scrollContentsBy(int dx, int dy); 187 #endif 188 #if defined(Q_WS_MAC) 189 void updateDockIcon(); 190 void updateDockOverlay(); 191 void setDockIconEnabled(bool aOn) { mDockIconEnabled = aOn; }; 192 void setMouseCoalescingEnabled(bool aOn); 193 #endif 194 void onStateChange(KMachineState state); 195 void captureKbd(bool aCapture, bool aEmitSignal = true); 196 void captureMouse(bool aCapture, bool aEmitSignal = true); 197 bool processHotKey(const QKeySequence &key, const QList<QAction*> &data); 198 void releaseAllPressedKeys(bool aReleaseHostKey = true); 232 199 void saveKeyStates(); 233 200 void sendChangedKeyStates(); 234 201 void updateMouseClipping(); 235 236 void setPointerShape (MousePointerChangeEvent *me); 237 238 bool isRunning() 239 { 240 return mLastState == KMachineState_Running 241 || mLastState == KMachineState_Teleporting 242 || mLastState == KMachineState_LiveSnapshotting; 243 } 244 245 static void dimImage (QImage &img); 246 247 private slots: 248 249 void doResizeHint (const QSize &aSize = QSize()); 250 void doResizeDesktop (int); 251 252 private: 253 254 enum DesktopGeo 255 { 256 DesktopGeo_Invalid = 0, DesktopGeo_Fixed, 257 DesktopGeo_Automatic, DesktopGeo_Any 258 }; 259 260 void setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight); 261 void storeConsoleSize (int aWidth, int aHeight); 262 void calculateDesktopGeometry(); 263 void maybeRestrictMinimumSize(); 264 QRect availableGeometry() const; 265 266 VBoxConsoleWnd *mMainWnd; 267 268 CConsole mConsole; 269 270 const VBoxGlobalSettings &gs; 271 202 void setPointerShape(MousePointerChangeEvent *pEvent); 203 204 enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any }; 205 void storeConsoleSize(int aWidth, int aHeight); 206 void setMouseIntegrationLocked(bool bDisabled); 207 void setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight); 208 virtual void maybeRestrictMinimumSize() = 0; 209 QRect availableGeometry(); 210 211 static void dimImage(QImage &img); 212 213 /* Private members: */ 214 UIMachineWindow *m_pMachineWindow; 215 CConsole m_console; 216 const VBoxGlobalSettings &m_globalSettings; 272 217 KMachineState mLastState; 273 218 274 bool mAttached : 1;275 bool mKbdCaptured : 1;276 bool mMouseCaptured : 1;277 bool mMouseAbsolute : 1;278 bool mMouseIntegration : 1;279 219 QPoint mLastPos; 280 220 QPoint mCapturedPos; 281 221 int m_iLastMouseWheelDelta; 282 222 283 bool mDisableAutoCapture : 1;284 285 223 enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 }; 286 uint8_t mPressedKeys [128]; 287 uint8_t mPressedKeysCopy [128]; 288 289 bool mIsHostkeyPressed : 1; 290 bool mIsHostkeyAlone : 1; 291 292 /** mKbdCaptured value during the the last host key press or release */ 224 uint8_t mPressedKeys[128]; 225 uint8_t mPressedKeysCopy[128]; 226 227 long muNumLockAdaptionCnt; 228 long muCapsLockAdaptionCnt; 229 230 bool m_bIsAutoCaptureDisabled : 1; 231 bool m_bIsKeyboardCaptured : 1; 232 bool m_bIsMouseCaptured : 1; 233 bool m_bIsMouseAbsolute : 1; 234 bool m_bIsMouseIntegrated : 1; 235 bool m_bIsHostkeyPressed : 1; 236 bool m_bIsHostkeyAlone : 1; 293 237 bool hostkey_in_capture : 1; 294 295 bool mIgnoreMainwndResize : 1; 296 bool mAutoresizeGuest : 1; 297 bool mIgnoreFrameBufferResize : 1; 298 bool mIgnoreGuestResize : 1; 299 300 /** 301 * This flag indicates whether the last console resize should trigger 302 * a size hint to the guest. This is important particularly when 303 * enabling the autoresize feature to know whether to send a hint. 304 */ 238 bool m_bIsMachineWindowResizeIgnored : 1; 239 bool m_bIsFrameBufferResizeIgnored : 1; 240 bool m_bIsGuestResizeIgnored : 1; 305 241 bool mDoResize : 1; 306 307 bool mGuestSupportsGraphics : 1;308 309 242 bool mNumLock : 1; 310 243 bool mScrollLock : 1; 311 244 bool mCapsLock : 1; 312 long muNumLockAdaptionCnt; 313 long muCapsLockAdaptionCnt; 314 315 316 VBoxDefs::RenderMode mode; 245 317 246 #ifdef VBOX_WITH_VIDEOHWACCEL 318 247 bool mAccelerate2DVideo; 319 248 #endif 320 321 QRegion mLastVisibleRegion;322 QSize mNormalSize;323 249 324 250 #if defined(Q_WS_WIN) … … 337 263 #endif 338 264 339 VBoxFrameBuffer *mFrameBuf;265 UIFrameBuffer *mFrameBuf; 340 266 CConsoleCallback mCallback; 341 342 friend class VBoxConsoleCallback;343 344 #if defined (Q_WS_WIN32)345 static LRESULT CALLBACK lowLevelKeyboardProc (int nCode,346 WPARAM wParam, LPARAM lParam);347 #elif defined (Q_WS_MAC)348 # if defined (QT_MAC_USE_COCOA)349 static bool darwinEventHandlerProc (const void *pvCocoaEvent, const350 void *pvCarbonEvent, void *pvUser);351 # elif !defined (VBOX_WITH_HACKED_QT)352 static pascal OSStatus darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef,353 EventRef inEvent, void *inUserData);354 # else /* VBOX_WITH_HACKED_QT */355 static bool macEventFilter (EventRef inEvent, void *inUserData);356 # endif /* VBOX_WITH_HACKED_QT */357 #endif358 267 359 268 QPixmap mPausedShot; … … 371 280 bool mHideHostPointer; 372 281 QCursor mLastCursor; 282 283 friend class UIConsoleCallback; 373 284 }; 374 285 375 #endif // !___VBoxConsoleView_h___ 376 286 #endif // !___UIMachineViewNormal_h___ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass implementation4 * UIMachineWindow class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010 Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 23 23 /* Global includes */ 24 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 25 # include "precomp.h" 26 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 27 #include <QActionGroup> 28 #include <QDesktopWidget> 29 #include <QDir> 30 #include <QFileInfo> 31 #include <QMenuBar> 32 #include <QProgressBar> 33 #include <QTimer> 34 35 #ifdef Q_WS_X11 36 # include <QX11Info> 37 #endif 38 #ifdef Q_WS_MAC 39 # include <QPainter> 40 #endif 24 #include <QCloseEvent> 41 25 42 26 /* Local includes */ 43 #include "QIFileDialog.h" 44 #include "QIHotKeyEdit.h" 45 #include "QIHttp.h" 46 #include "QIStateIndicator.h" 47 #include "QIStatusBar.h" 48 #include "QIWidgetValidator.h" 49 #include "QIHotKeyEdit.h" 50 #include "VBoxConsoleWnd.h" 51 #include "VBoxConsoleView.h" 27 #include "VBoxGlobal.h" 28 #include "VBoxProblemReporter.h" 52 29 #include "VBoxCloseVMDlg.h" 53 #include "VBoxDownloaderWgt.h" 54 #include "VBoxGlobal.h" 55 #include "VBoxMediaManagerDlg.h" 56 #include "VBoxMiniToolBar.h" 57 #include "VBoxProblemReporter.h" 58 #include "VBoxTakeSnapshotDlg.h" 59 #include "UIFirstRunWzd.h" 60 #include "VBoxVMSettingsNetwork.h" 61 #include "VBoxVMSettingsSF.h" 62 #include "VBoxVMInformationDlg.h" 63 64 #ifdef Q_WS_X11 65 # include <X11/Xlib.h> 66 # include <XKeyboard.h> 67 #endif 68 #ifdef Q_WS_MAC 69 # include "VBoxUtils.h" 70 # include "VBoxIChatTheaterWrapper.h" 71 # include <ApplicationServices/ApplicationServices.h> 72 #endif 73 #ifdef VBOX_WITH_DEBUGGER_GUI 74 # include <VBox/err.h> 75 # include <iprt/ldr.h> 76 #endif 77 78 #include <VBox/VMMDev.h> /** @todo @bugref{4084} */ 79 #include <iprt/buildconfig.h> 80 #include <iprt/param.h> 81 #include <iprt/path.h> 82 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 83 84 /* Global forwards */ 85 extern void qt_set_sequence_auto_mnemonic (bool on); 86 87 /** class StatusTipEvent 88 * 89 * The StatusTipEvent class is an auxiliary QEvent class 90 * for carrying statusTip text of non-QAction menu item's. 91 * This event is posted then the menu item is highlighted but 92 * processed later in VBoxConsoleWnd::event() handler to 93 * avoid statusBar messaging collisions. 94 */ 95 class StatusTipEvent : public QEvent 96 { 97 public: 98 enum { Type = QEvent::User + 10 }; 99 StatusTipEvent (const QString &aTip) 100 : QEvent ((QEvent::Type) Type), mTip (aTip) {} 101 102 QString mTip; 103 }; 104 105 class VBoxAdditionsDownloader : public VBoxDownloaderWgt 106 { 107 Q_OBJECT; 108 109 public: 110 111 VBoxAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 112 : VBoxDownloaderWgt (aSource, aTarget) 113 , mAction (aAction) 114 { 115 mAction->setEnabled (false); 116 retranslateUi(); 117 } 118 119 void start() 120 { 121 acknowledgeStart(); 122 } 123 124 protected: 125 126 void retranslateUi() 127 { 128 mCancelButton->setText (tr ("Cancel")); 129 mProgressBar->setToolTip (tr ("Downloading the VirtualBox Guest Additions " 130 "CD image from <nobr><b>%1</b>...</nobr>") 131 .arg (mSource.toString())); 132 mCancelButton->setToolTip (tr ("Cancel the VirtualBox Guest " 133 "Additions CD image download")); 134 } 135 136 private slots: 137 138 void downloadFinished (bool aError) 139 { 140 if (aError) 141 VBoxDownloaderWgt::downloadFinished (aError); 142 else 30 31 #include "UIMachineLogic.h" 32 #include "UIMachineWindow.h" 33 #include "UIMachineView.h" 34 #include "UIMachineWindowNormal.h" 35 //#include "UIMachineWindowFullscreen.h" 36 //#include "UIMachineWindowSeamless.h" 37 38 UIMachineWindow* UIMachineWindow::create(UIMachineLogic *pMachineLogic, UIVisualStateType visualStateType) 39 { 40 UIMachineWindow *window = 0; 41 switch (visualStateType) 42 { 43 case UIVisualStateType_Normal: 44 window = new UIMachineWindowNormal(pMachineLogic); 45 break; 46 case UIVisualStateType_Fullscreen: 47 // window = new UIMachineWindowFullscreen(pMachineLogic); 48 window = new UIMachineWindowNormal(pMachineLogic); 49 break; 50 case UIVisualStateType_Seamless: 51 // window = new UIMachineWindowSeamless(pMachineLogic); 52 window = new UIMachineWindowNormal(pMachineLogic); 53 break; 54 } 55 return window; 56 } 57 58 UIMachineWindow::UIMachineWindow(UIMachineLogic *pMachineLogic) 59 : m_pMachineLogic(pMachineLogic) 60 { 61 /* Prepare window icon: */ 62 prepareWindowIcon(); 63 64 /* Load common window settings: */ 65 loadWindowSettings(); 66 67 /* Translate common window: */ 68 retranslateWindow(); 69 } 70 71 UIMachineWindow::~UIMachineWindow() 72 { 73 // Nothing for now! 74 } 75 76 void UIMachineWindow::retranslateWindow() 77 { 78 #ifdef VBOX_OSE 79 m_strWindowTitlePrefix = UIMachineLogic::tr("VirtualBox OSE"); 80 #else 81 m_strWindowTitlePrefix = UIMachineLogic::tr("Sun VirtualBox"); 82 #endif 83 #ifdef VBOX_BLEEDING_EDGE 84 m_strWindowTitlePrefix += UIMachineLogic::tr(" EXPERIMENTAL build %1r%2 - %3") 85 .arg(RTBldCfgVersion()) 86 .arg(RTBldCfgRevisionStr()) 87 .arg(VBOX_BLEEDING_EDGE); 88 #endif 89 } 90 91 void UIMachineWindow::updateAppearanceOf(int iElement) 92 { 93 CMachine machine = machineLogic()->session().GetMachine(); 94 95 if (iElement & UIVisualElement_WindowCaption) 96 { 97 QString strSnapshotName; 98 if (machine.GetSnapshotCount() > 0) 143 99 { 144 QByteArray receivedData (mHttp->readAll()); 145 /* Serialize the incoming buffer into the .iso image. */ 146 while (true) 147 { 148 QFile file (mTarget); 149 if (file.open (QIODevice::WriteOnly)) 150 { 151 file.write (receivedData); 152 file.close(); 153 if (vboxProblem().confirmMountAdditions (mSource.toString(), 154 QDir::toNativeSeparators (mTarget))) 155 vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 156 QTimer::singleShot (0, this, SLOT (suicide())); 157 break; 158 } 159 else 160 { 161 vboxProblem().message (window(), VBoxProblemReporter::Error, 162 tr ("<p>Failed to save the downloaded file as " 163 "<nobr><b>%1</b>.</nobr></p>") 164 .arg (QDir::toNativeSeparators (mTarget))); 165 } 166 167 QString target = QIFileDialog::getExistingDirectory ( 168 QFileInfo (mTarget).absolutePath(), this, 169 tr ("Select folder to save Guest Additions image to"), true); 170 if (target.isNull()) 171 QTimer::singleShot (0, this, SLOT (suicide())); 172 else 173 mTarget = QDir (target).absoluteFilePath (QFileInfo (mTarget).fileName()); 174 } 100 CSnapshot snapshot = machine.GetCurrentSnapshot(); 101 strSnapshotName = " (" + snapshot.GetName() + ")"; 175 102 } 176 } 177 178 void suicide() 179 { 180 QStatusBar *sb = qobject_cast <QStatusBar*> (parent()); 181 Assert (sb); 182 sb->removeWidget (this); 183 mAction->setEnabled (true); 184 VBoxDownloaderWgt::suicide(); 185 } 186 187 private: 188 189 bool confirmDownload() 190 { 191 return vboxProblem().confirmDownloadAdditions (mSource.toString(), 192 mHttp->lastResponse().contentLength()); 193 } 194 195 void warnAboutError (const QString &aError) 196 { 197 return vboxProblem().cannotDownloadGuestAdditions (mSource.toString(), aError); 198 } 199 200 QAction *mAction; 201 }; 202 203 struct MountTarget 204 { 205 MountTarget() : name (QString ("")), port (0), device (0), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 206 MountTarget (const QString &aName, LONG aPort, LONG aDevice) 207 : name (aName), port (aPort), device (aDevice), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 208 MountTarget (const QString &aName, LONG aPort, LONG aDevice, const QString &aId) 209 : name (aName), port (aPort), device (aDevice), id (aId), type (VBoxDefs::MediumType_Invalid) {} 210 MountTarget (const QString &aName, LONG aPort, LONG aDevice, VBoxDefs::MediumType aType) 211 : name (aName), port (aPort), device (aDevice), id (QString()), type (aType) {} 212 QString name; 213 LONG port; 214 LONG device; 215 QString id; 216 VBoxDefs::MediumType type; 217 }; 218 Q_DECLARE_METATYPE (MountTarget); 219 220 int searchMaxSnapshotIndex (const CMachine &aMachine, const CSnapshot &aSnapshot, const QString &aNameTemplate) 221 { 222 int maxIndex = 0; 223 QRegExp regExp (QString ("^") + aNameTemplate.arg ("([0-9]+)") + QString ("$")); 224 if (!aSnapshot.isNull()) 225 { 226 /* Check the current snapshot name */ 227 QString name = aSnapshot.GetName(); 228 int pos = regExp.indexIn (name); 229 if (pos != -1) 230 maxIndex = regExp.cap (1).toInt() > maxIndex ? regExp.cap (1).toInt() : maxIndex; 231 /* Traversing all the snapshot children */ 232 foreach (const CSnapshot &child, aSnapshot.GetChildren()) 233 { 234 int maxIndexOfChildren = searchMaxSnapshotIndex (aMachine, child, aNameTemplate); 235 maxIndex = maxIndexOfChildren > maxIndex ? maxIndexOfChildren : maxIndex; 236 } 237 } 238 return maxIndex; 239 } 240 241 /** \class VBoxConsoleWnd 242 * 243 * The VBoxConsoleWnd class is a VM console window, one of two main VBox 244 * GUI windows. 245 * 246 * This window appears when the user starts the virtual machine. It 247 * contains the VBoxConsoleView widget that acts as a console of the 248 * running virtual machine. 249 */ 250 251 /** 252 * Constructs the VM console window. 253 * 254 * @param aSelf pointer to a variable where to store |this| right after 255 * this object's constructor is called (necessary to avoid 256 * recursion in VBoxGlobal::consoleWnd()) 257 */ 258 VBoxConsoleWnd::VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent, Qt::WindowFlags aFlags /* = Qt::Window */) 259 : QIWithRetranslateUI2 <QMainWindow> (aParent, aFlags) 260 /* Machine State */ 261 , mMachineState (KMachineState_Null) 262 /* Window Variables */ 263 , mConsoleStyle (0) 264 /* Menu Items */ 265 , mMainMenu (0) 266 , mVMMenu (0) 267 , mVMMenuMini (0) 268 , mDevicesMenu (0) 269 , mDevicesCDMenu (0) 270 , mDevicesFDMenu (0) 271 , mDevicesNetworkMenu (0) 272 , mDevicesSFMenu (0) 273 , mDevicesUSBMenu (0) 274 , mVmDisMouseIntegrMenu (0) 275 #if 0 /* TODO: Allow to setup status-bar! */ 276 , mDevicesVRDPMenu (0) 277 , mVmAutoresizeMenu (0) 278 #endif 279 #ifdef VBOX_WITH_DEBUGGER_GUI 280 , mDbgMenu (0) 281 #endif 282 , mHelpMenu (0) 283 /* Action Groups */ 284 , mRunningActions (0) 285 , mRunningOrPausedActions (0) 286 /* Machine Menu Actions */ 287 , mVmFullscreenAction (0) 288 , mVmSeamlessAction (0) 289 , mVmAutoresizeGuestAction (0) 290 , mVmAdjustWindowAction (0) 291 , mVmDisableMouseIntegrAction (0) 292 , mVmTypeCADAction (0) 293 #ifdef Q_WS_X11 294 , mVmTypeCABSAction (0) 295 #endif 296 , mVmTakeSnapshotAction (0) 297 , mVmShowInformationDlgAction (0) 298 , mVmResetAction (0) 299 , mVmPauseAction (0) 300 , mVmACPIShutdownAction (0) 301 , mVmCloseAction (0) 302 /* Device Menu Actions */ 303 , mDevicesNetworkDialogAction (0) 304 , mDevicesSFDialogAction (0) 305 , mDevicesSwitchVrdpSeparator (0) 306 , mDevicesSwitchVrdpAction (0) 307 , mDevicesInstallGuestToolsAction (0) 308 #ifdef VBOX_WITH_DEBUGGER_GUI 309 /* Debug Menu Actions */ 310 , mDbgStatisticsAction (0) 311 , mDbgCommandLineAction (0) 312 , mDbgLoggingAction (0) 313 #endif 314 /* Widgets */ 315 , mConsole (0) 316 , mMiniToolBar (0) 317 #ifdef VBOX_WITH_DEBUGGER_GUI 318 , mDbgGui (0) 319 , mDbgGuiVT (0) 320 #endif 321 /* LED Update Timer */ 322 , mIdleTimer (new QTimer (this)) 323 /* LEDs */ 324 , mHDLed (0) 325 , mCDLed (0) 326 #if 0 /* TODO: Allow to setup status-bar! */ 327 , mFDLed (0) 328 #endif 329 , mNetLed (0) 330 , mUSBLed (0) 331 , mSFLed (0) 332 , mVirtLed (0) 333 , mMouseLed (0) 334 , mHostkeyLed (0) 335 , mHostkeyLedContainer (0) 336 , mHostkeyName (0) 337 #if 0 /* TODO: Allow to setup status-bar! */ 338 , mVrdpLed (0) 339 , mAutoresizeLed (0) 340 #endif 341 , mIsOpenViewFinished (false) 342 , mIsFirstTimeStarted (false) 343 , mIsAutoSaveMedia (true) 344 , mNoAutoClose (false) 345 , mIsFullscreen (false) 346 , mIsSeamless (false) 347 , mIsSeamlessSupported (false) 348 , mIsGraphicsSupported (false) 349 , mIsWaitingModeResize (false) 350 , mWasMax (false) 351 { 352 if (aSelf) 353 *aSelf = this; 354 355 /* Cache IMedium data! */ 356 vboxGlobal().startEnumeratingMedia(); 357 358 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 359 /* The default application icon (will change to the VM-specific icon in 360 * openView()). On Win32, it's built-in to the executable. On Mac OS X the 361 * icon referenced in info.plist is used. */ 362 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 363 #endif 364 365 /* Ensure status bar is created */ 366 setStatusBar (new QIStatusBar (this)); 367 368 /* A group for all actions that are enabled only when the VM is running. 369 * Note that only actions whose enabled state depends exclusively on the 370 * execution state of the VM are added to this group. */ 371 mRunningActions = new QActionGroup (this); 372 mRunningActions->setExclusive (false); 373 374 /* A group for all actions that are enabled when the VM is running or 375 * paused. Note that only actions whose enabled state depends exclusively 376 * on the execution state of the VM are added to this group. */ 377 mRunningOrPausedActions = new QActionGroup (this); 378 mRunningOrPausedActions->setExclusive (false); 379 380 /* VM menu actions */ 381 mVmFullscreenAction = new QAction (this); 382 mVmFullscreenAction->setIcon (VBoxGlobal::iconSetOnOff ( 383 ":/fullscreen_on_16px.png", ":/fullscreen_16px.png", 384 ":/fullscreen_on_disabled_16px.png", ":/fullscreen_disabled_16px.png")); 385 mVmFullscreenAction->setCheckable (true); 386 387 mVmSeamlessAction = new QAction (this); 388 mVmSeamlessAction->setIcon (VBoxGlobal::iconSetOnOff ( 389 ":/seamless_on_16px.png", ":/seamless_16px.png", 390 ":/seamless_on_disabled_16px.png", ":/seamless_disabled_16px.png")); 391 mVmSeamlessAction->setCheckable (true); 392 393 mVmAutoresizeGuestAction = new QAction (mRunningActions); 394 mVmAutoresizeGuestAction->setIcon (VBoxGlobal::iconSetOnOff ( 395 ":/auto_resize_on_on_16px.png", ":/auto_resize_on_16px.png", 396 ":/auto_resize_on_on_disabled_16px.png", ":/auto_resize_on_disabled_16px.png")); 397 mVmAutoresizeGuestAction->setCheckable (true); 398 mVmAutoresizeGuestAction->setEnabled (false); 399 400 mVmAdjustWindowAction = new QAction (this); 401 mVmAdjustWindowAction->setIcon (VBoxGlobal::iconSet ( 402 ":/adjust_win_size_16px.png", ":/adjust_win_size_disabled_16px.png")); 403 404 mVmDisableMouseIntegrAction = new QAction (this); 405 mVmDisableMouseIntegrAction->setIcon (VBoxGlobal::iconSetOnOff ( 406 ":/mouse_can_seamless_on_16px.png", ":/mouse_can_seamless_16px.png", 407 ":/mouse_can_seamless_on_disabled_16px.png", ":/mouse_can_seamless_disabled_16px.png")); 408 mVmDisableMouseIntegrAction->setCheckable (true); 409 410 mVmTypeCADAction = new QAction (mRunningActions); 411 mVmTypeCADAction->setIcon (VBoxGlobal::iconSet ( 412 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 413 414 #if defined(Q_WS_X11) 415 mVmTypeCABSAction = new QAction (mRunningActions); 416 mVmTypeCABSAction->setIcon (VBoxGlobal::iconSet ( 417 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 418 #endif 419 420 mVmTakeSnapshotAction = new QAction (mRunningOrPausedActions); 421 mVmTakeSnapshotAction->setIcon (VBoxGlobal::iconSet ( 422 ":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png")); 423 424 mVmShowInformationDlgAction = new QAction (this); 425 mVmShowInformationDlgAction->setIcon (VBoxGlobal::iconSet ( 426 ":/session_info_16px.png", ":/session_info_disabled_16px.png")); 427 428 mVmResetAction = new QAction (mRunningActions); 429 mVmResetAction->setIcon (VBoxGlobal::iconSet ( 430 ":/reset_16px.png", ":/reset_disabled_16px.png")); 431 432 mVmPauseAction = new QAction (this); 433 mVmPauseAction->setIcon (VBoxGlobal::iconSet ( 434 ":/pause_16px.png", ":/pause_disabled_16px.png")); 435 mVmPauseAction->setCheckable (true); 436 437 mVmACPIShutdownAction = new QAction (mRunningActions); 438 mVmACPIShutdownAction->setIcon (VBoxGlobal::iconSet ( 439 ":/acpi_16px.png", ":/acpi_disabled_16px.png")); 440 441 mVmCloseAction = new QAction (this); 442 mVmCloseAction->setMenuRole (QAction::QuitRole); 443 mVmCloseAction->setIcon (VBoxGlobal::iconSet (":/exit_16px.png")); 444 445 /* Devices menu actions */ 446 mDevicesNetworkDialogAction = new QAction (mRunningOrPausedActions); 447 mDevicesNetworkDialogAction->setIcon (VBoxGlobal::iconSet ( 448 ":/nw_16px.png", ":/nw_disabled_16px.png")); 449 450 mDevicesSFDialogAction = new QAction (mRunningOrPausedActions); 451 mDevicesSFDialogAction->setIcon (VBoxGlobal::iconSet ( 452 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")); 453 454 mDevicesSwitchVrdpAction = new QAction (mRunningOrPausedActions); 455 mDevicesSwitchVrdpAction->setIcon (VBoxGlobal::iconSetOnOff ( 456 ":/vrdp_on_16px.png", ":/vrdp_16px.png", 457 ":/vrdp_on_disabled_16px.png", ":/vrdp_disabled_16px.png")); 458 mDevicesSwitchVrdpAction->setCheckable (true); 459 460 mDevicesInstallGuestToolsAction = new QAction (mRunningActions); 461 mDevicesInstallGuestToolsAction->setIcon (VBoxGlobal::iconSet ( 462 ":/guesttools_16px.png", ":/guesttools_disabled_16px.png")); 463 464 #ifdef VBOX_WITH_DEBUGGER_GUI 465 /* Debug menu actions */ 466 if (vboxGlobal().isDebuggerEnabled()) 467 { 468 mDbgStatisticsAction = new QAction (this); 469 mDbgCommandLineAction = new QAction (this); 470 if (vboxGlobal().getDebuggerModule()== NIL_RTLDRMOD) 471 { 472 mDbgStatisticsAction->setEnabled (false); 473 mDbgCommandLineAction->setEnabled (false); 474 } 475 mDbgLoggingAction = new QAction (this); 476 mDbgLoggingAction->setCheckable (true); 477 } 478 else 479 { 480 mDbgStatisticsAction = 0; 481 mDbgCommandLineAction = 0; 482 mDbgLoggingAction = 0; 483 } 484 #endif 485 486 /* Help menu actions */ 487 mHelpActions.setup (this); 488 489 /* Menu Items */ 490 mMainMenu = new QIMenu (this); 491 mDevicesCDMenu = new QMenu (this); 492 mDevicesFDMenu = new QMenu (this); 493 mDevicesNetworkMenu = new QMenu (this); 494 mDevicesSFMenu = new QMenu (this); 495 mDevicesUSBMenu = new VBoxUSBMenu (this); 496 497 /* Machine submenu */ 498 mVMMenu = menuBar()->addMenu (QString::null); 499 mMainMenu->addMenu (mVMMenu); 500 mVmDisMouseIntegrMenu = new VBoxSwitchMenu (mVMMenu, mVmDisableMouseIntegrAction, true); 501 #if 0 /* TODO: Allow to setup status-bar! */ 502 mVmAutoresizeMenu = new VBoxSwitchMenu (mVMMenu, mVmAutoresizeGuestAction); 503 #endif 504 505 mVMMenu->addAction (mVmFullscreenAction); 506 mVMMenu->addAction (mVmSeamlessAction); 507 mVMMenu->addAction (mVmAutoresizeGuestAction); 508 mVMMenu->addAction (mVmAdjustWindowAction); 509 mVMMenu->addSeparator(); 510 mVMMenu->addAction (mVmDisableMouseIntegrAction); 511 mVMMenu->addSeparator(); 512 mVMMenu->addAction (mVmTypeCADAction); 513 #ifdef Q_WS_X11 514 mVMMenu->addAction (mVmTypeCABSAction); 515 #endif 516 mVMMenu->addSeparator(); 517 mVMMenu->addAction (mVmTakeSnapshotAction); 518 mVMMenu->addSeparator(); 519 mVMMenu->addAction (mVmShowInformationDlgAction); 520 mVMMenu->addSeparator(); 521 mVMMenu->addAction (mVmResetAction); 522 mVMMenu->addAction (mVmPauseAction); 523 mVMMenu->addAction (mVmACPIShutdownAction); 524 #ifndef Q_WS_MAC 525 mVMMenu->addSeparator(); 526 #endif /* Q_WS_MAC */ 527 mVMMenu->addAction (mVmCloseAction); 528 529 /* Devices submenu */ 530 mDevicesMenu = menuBar()->addMenu (QString::null); 531 mMainMenu->addMenu (mDevicesMenu); 532 533 mDevicesCDMenu->setIcon (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png")); 534 mDevicesFDMenu->setIcon (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png")); 535 mDevicesUSBMenu->setIcon (VBoxGlobal::iconSet (":/usb_16px.png", ":/usb_disabled_16px.png")); 536 537 mDevicesMenu->addMenu (mDevicesCDMenu); 538 mDevicesMenu->addMenu (mDevicesFDMenu); 539 mDevicesMenu->addAction (mDevicesNetworkDialogAction); 540 mDevicesMenu->addAction (mDevicesSFDialogAction); 541 mDevicesMenu->addMenu (mDevicesUSBMenu); 542 543 #if 0 /* TODO: Allow to setup status-bar! */ 544 mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, mDevicesSwitchVrdpAction); 545 #endif 546 mDevicesSwitchVrdpSeparator = mDevicesMenu->addSeparator(); 547 mDevicesMenu->addAction (mDevicesSwitchVrdpAction); 548 549 mDevicesMenu->addSeparator(); 550 mDevicesMenu->addAction (mDevicesInstallGuestToolsAction); 551 552 #ifdef VBOX_WITH_DEBUGGER_GUI 553 /* Debug submenu */ 554 if (vboxGlobal().isDebuggerEnabled()) 555 { 556 mDbgMenu = menuBar()->addMenu (QString::null); 557 mMainMenu->addMenu (mDbgMenu); 558 mDbgMenu->addAction (mDbgStatisticsAction); 559 mDbgMenu->addAction (mDbgCommandLineAction); 560 mDbgMenu->addAction (mDbgLoggingAction); 561 } 562 else 563 mDbgMenu = 0; 564 #endif 565 566 /* Help submenu */ 567 mHelpMenu = menuBar()->addMenu (QString::null); 568 mMainMenu->addMenu (mHelpMenu); 569 mHelpActions.addTo (mHelpMenu); 570 571 /* Machine submenu for mini-toolbar */ 572 mVMMenuMini = new QMenu (this); 573 mVMMenuMini->addAction (mVmTypeCADAction); 574 #ifdef Q_WS_X11 575 mVMMenuMini->addAction (mVmTypeCABSAction); 576 #endif 577 mVMMenuMini->addSeparator(); 578 mVMMenuMini->addAction (mVmTakeSnapshotAction); 579 mVMMenuMini->addSeparator(); 580 mVMMenuMini->addAction (mVmShowInformationDlgAction); 581 mVMMenuMini->addSeparator(); 582 mVMMenuMini->addAction (mVmResetAction); 583 mVMMenuMini->addAction (mVmPauseAction); 584 mVMMenuMini->addAction (mVmACPIShutdownAction); 585 586 /* Status bar */ 587 QWidget *indicatorBox = new QWidget; 588 QHBoxLayout *indicatorBoxHLayout = new QHBoxLayout (indicatorBox); 589 VBoxGlobal::setLayoutMargin (indicatorBoxHLayout, 0); 590 indicatorBoxHLayout->setSpacing (5); 591 592 /* i/o devices */ 593 mHDLed = new QIStateIndicator (KDeviceActivity_Idle); 594 mHDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/hd_16px.png")); 595 mHDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/hd_read_16px.png")); 596 mHDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/hd_write_16px.png")); 597 mHDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/hd_disabled_16px.png")); 598 indicatorBoxHLayout->addWidget (mHDLed); 599 mCDLed = new QIStateIndicator (KDeviceActivity_Idle); 600 mCDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/cd_16px.png")); 601 mCDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/cd_read_16px.png")); 602 mCDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/cd_write_16px.png")); 603 mCDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/cd_disabled_16px.png")); 604 indicatorBoxHLayout->addWidget (mCDLed); 605 #if 0 /* TODO: Allow to setup status-bar! */ 606 mFDLed = new QIStateIndicator (KDeviceActivity_Idle); 607 mFDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/fd_16px.png")); 608 mFDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/fd_read_16px.png")); 609 mFDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/fd_write_16px.png")); 610 mFDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/fd_disabled_16px.png")); 611 indicatorBoxHLayout->addWidget (mFDLed); 612 #endif 613 mNetLed = new QIStateIndicator (KDeviceActivity_Idle); 614 mNetLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/nw_16px.png")); 615 mNetLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/nw_read_16px.png")); 616 mNetLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/nw_write_16px.png")); 617 mNetLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/nw_disabled_16px.png")); 618 indicatorBoxHLayout->addWidget (mNetLed); 619 mUSBLed = new QIStateIndicator (KDeviceActivity_Idle); 620 mUSBLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/usb_16px.png")); 621 mUSBLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/usb_read_16px.png")); 622 mUSBLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/usb_write_16px.png")); 623 mUSBLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/usb_disabled_16px.png")); 624 indicatorBoxHLayout->addWidget (mUSBLed); 625 mSFLed = new QIStateIndicator (KDeviceActivity_Idle); 626 mSFLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/shared_folder_16px.png")); 627 mSFLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/shared_folder_read_16px.png")); 628 mSFLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/shared_folder_write_16px.png")); 629 mSFLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/shared_folder_disabled_16px.png")); 630 indicatorBoxHLayout->addWidget (mSFLed); 631 632 /* virtualization */ 633 mVirtLed = new QIStateIndicator (0); 634 mVirtLed->setStateIcon (0, QPixmap (":/vtx_amdv_disabled_16px.png")); 635 mVirtLed->setStateIcon (1, QPixmap (":/vtx_amdv_16px.png")); 636 indicatorBoxHLayout->addWidget (mVirtLed); 637 638 QFrame *separator = new QFrame(); 639 separator->setFrameStyle (QFrame::VLine | QFrame::Sunken); 640 indicatorBoxHLayout->addWidget (separator); 641 642 /* mouse */ 643 mMouseLed = new QIStateIndicator (0); 644 mMouseLed->setStateIcon (0, QPixmap (":/mouse_disabled_16px.png")); 645 mMouseLed->setStateIcon (1, QPixmap (":/mouse_16px.png")); 646 mMouseLed->setStateIcon (2, QPixmap (":/mouse_seamless_16px.png")); 647 mMouseLed->setStateIcon (3, QPixmap (":/mouse_can_seamless_16px.png")); 648 mMouseLed->setStateIcon (4, QPixmap (":/mouse_can_seamless_uncaptured_16px.png")); 649 indicatorBoxHLayout->addWidget (mMouseLed); 650 651 /* host key */ 652 mHostkeyLedContainer = new QWidget; 653 QHBoxLayout *hostkeyLEDContainerLayout = new QHBoxLayout (mHostkeyLedContainer); 654 VBoxGlobal::setLayoutMargin (hostkeyLEDContainerLayout, 0); 655 hostkeyLEDContainerLayout->setSpacing (3); 656 indicatorBoxHLayout->addWidget (mHostkeyLedContainer); 657 658 mHostkeyLed = new QIStateIndicator (0); 659 mHostkeyLed->setStateIcon (0, QPixmap (":/hostkey_16px.png")); 660 mHostkeyLed->setStateIcon (1, QPixmap (":/hostkey_captured_16px.png")); 661 mHostkeyLed->setStateIcon (2, QPixmap (":/hostkey_pressed_16px.png")); 662 mHostkeyLed->setStateIcon (3, QPixmap (":/hostkey_captured_pressed_16px.png")); 663 hostkeyLEDContainerLayout->addWidget (mHostkeyLed); 664 mHostkeyName = new QLabel (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 665 hostkeyLEDContainerLayout->addWidget (mHostkeyName); 666 667 #if 0 /* TODO: Allow to setup status-bar! */ 668 /* VRDP Led */ 669 mVrdpLed = new QIStateIndicator (0, indicatorBox, "mVrdpLed", Qt::WNoAutoErase); 670 mVrdpLed->setStateIcon (0, QPixmap (":/vrdp_disabled_16px.png")); 671 mVrdpLed->setStateIcon (1, QPixmap (":/vrdp_16px.png")); 672 /* Auto-Resize LED */ 673 mAutoresizeLed = new QIStateIndicator (1, indicatorBox, "mAutoresizeLed", Qt::WNoAutoErase); 674 mAutoresizeLed->setStateIcon (0, QPixmap (":/auto_resize_off_disabled_16px.png")); 675 mAutoresizeLed->setStateIcon (1, QPixmap (":/auto_resize_off_16px.png")); 676 mAutoresizeLed->setStateIcon (2, QPixmap (":/auto_resize_on_disabled_16px.png")); 677 mAutoresizeLed->setStateIcon (3, QPixmap (":/auto_resize_on_16px.png")); 678 #endif 679 680 /* add to statusbar */ 681 statusBar()->addPermanentWidget (indicatorBox, 0); 682 683 /* Retranslate UI */ 684 retranslateUi(); 685 686 setWindowTitle (mCaptionPrefix); 687 688 /* Connections */ 689 connect (mVmFullscreenAction, SIGNAL (toggled (bool)), this, SLOT (vmFullscreen (bool))); 690 connect (mVmSeamlessAction, SIGNAL (toggled (bool)), this, SLOT (vmSeamless (bool))); 691 connect (mVmAutoresizeGuestAction, SIGNAL (toggled (bool)), this, SLOT (vmAutoresizeGuest (bool))); 692 connect (mVmAdjustWindowAction, SIGNAL (triggered()), this, SLOT (vmAdjustWindow())); 693 connect (mVmDisableMouseIntegrAction, SIGNAL (toggled (bool)), this, SLOT (vmDisableMouseIntegration (bool))); 694 connect (mVmTypeCADAction, SIGNAL (triggered()), this, SLOT (vmTypeCAD())); 695 #ifdef Q_WS_X11 696 connect (mVmTypeCABSAction, SIGNAL (triggered()), this, SLOT (vmTypeCABS())); 697 #endif 698 connect (mVmTakeSnapshotAction, SIGNAL (triggered()), this, SLOT (vmTakeSnapshot())); 699 connect (mVmShowInformationDlgAction, SIGNAL (triggered()), this, SLOT (vmShowInfoDialog())); 700 connect (mVmResetAction, SIGNAL (triggered()), this, SLOT (vmReset())); 701 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 702 connect (mVmACPIShutdownAction, SIGNAL (triggered()), this, SLOT (vmACPIShutdown())); 703 connect (mVmCloseAction, SIGNAL (triggered()), this, SLOT (vmClose())); 704 705 connect (mDevicesCDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 706 connect (mDevicesFDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 707 connect (mDevicesNetworkMenu, SIGNAL (aboutToShow()), this, SLOT (prepareNetworkMenu())); 708 connect (mDevicesSFMenu, SIGNAL (aboutToShow()), this, SLOT (prepareSFMenu())); 709 connect (mDevicesUSBMenu, SIGNAL(triggered (QAction *)), this, SLOT(switchUSB (QAction *))); 710 711 connect (mDevicesNetworkDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenNetworkDialog())); 712 connect (mDevicesSFDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenSFDialog())); 713 connect (mDevicesSwitchVrdpAction, SIGNAL (toggled (bool)), this, SLOT (devicesSwitchVrdp (bool))); 714 connect (mDevicesInstallGuestToolsAction, SIGNAL (triggered()), this, SLOT (devicesInstallGuestAdditions())); 715 716 connect (mCDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 717 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 718 #if 0 /* TODO: Allow to setup status-bar! */ 719 connect (mFDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 720 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 721 #endif 722 connect (mNetLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 723 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 724 connect (mUSBLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 725 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 726 connect (mSFLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 727 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 728 connect (mMouseLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 729 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 730 #if 0 /* TODO: Allow to setup status-bar! */ 731 connect (mVrdpLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 732 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 733 connect (mAutoresizeLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 734 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 735 #endif 736 737 /* Watch global settings changes */ 738 connect (&vboxGlobal().settings(), SIGNAL (propertyChanged (const char *, const char *)), 739 this, SLOT (processGlobalSettingChange (const char *, const char *))); 740 #ifdef Q_WS_MAC 741 connect (&vboxGlobal(), SIGNAL (dockIconUpdateChanged (const VBoxChangeDockIconUpdateEvent &)), 742 this, SLOT (changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &))); 743 connect (&vboxGlobal(), SIGNAL (presentationModeChanged (const VBoxChangePresentationModeEvent &)), 744 this, SLOT (changePresentationMode (const VBoxChangePresentationModeEvent &))); 745 #endif 746 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 if (mDbgMenu) 749 connect (mDbgMenu, SIGNAL (aboutToShow()), this, SLOT (dbgPrepareDebugMenu())); 750 if (mDbgStatisticsAction) 751 connect (mDbgStatisticsAction, SIGNAL (triggered()), this, SLOT (dbgShowStatistics())); 752 if (mDbgCommandLineAction) 753 connect (mDbgCommandLineAction, SIGNAL (triggered()), this, SLOT (dbgShowCommandLine())); 754 if (mDbgLoggingAction) 755 connect (mDbgLoggingAction, SIGNAL (toggled (bool)), this, SLOT (dbgLoggingToggled (bool))); 756 #endif 757 758 #ifdef Q_WS_MAC 759 /* For the status bar on Cocoa */ 760 setUnifiedTitleAndToolBarOnMac (true); 761 # ifdef VBOX_WITH_ICHAT_THEATER 762 // int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 }; 763 // HIWindowChangeAttributes (window, setAttr, 0); 764 initSharedAVManager(); 765 # endif 766 #endif 767 768 mMaskShift.scale (0, 0, Qt::IgnoreAspectRatio); 769 } 770 771 VBoxConsoleWnd::~VBoxConsoleWnd() 772 { 773 closeView(); 774 775 #ifdef VBOX_WITH_DEBUGGER_GUI 776 dbgDestroy(); 777 #endif 778 } 779 780 /** 781 * Opens a new console view to interact with a given VM. 782 * Does nothing if the console view is already opened. 783 * Used by VBoxGlobal::startMachine(), should not be called directly. 784 */ 785 bool VBoxConsoleWnd::openView (const CSession &aSession) 786 { 787 LogFlowFuncEnter(); 788 789 if (mConsole) 790 { 791 LogFlowFunc (("Already opened\n")); 792 LogFlowFuncLeave(); 793 return false; 794 } 795 796 #ifdef Q_WS_MAC 797 /* We have to make sure that we are getting the front most process. This is 798 * necessary for Qt versions > 4.3.3 */ 799 ProcessSerialNumber psn = { 0, kCurrentProcess }; 800 ::SetFrontProcess (&psn); 801 #endif /* Q_WS_MAC */ 802 803 mSession = aSession; 804 805 if (!centralWidget()) 806 { 807 setCentralWidget (new QWidget (this)); 808 QGridLayout *pMainLayout = new QGridLayout (centralWidget()); 809 VBoxGlobal::setLayoutMargin (pMainLayout, 0); 810 pMainLayout->setSpacing (0); 811 812 mShiftingSpacerLeft = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 813 mShiftingSpacerTop = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 814 mShiftingSpacerRight = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 815 mShiftingSpacerBottom = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 816 pMainLayout->addItem (mShiftingSpacerTop, 0, 0, 1, -1); 817 pMainLayout->addItem (mShiftingSpacerLeft, 1, 0); 818 pMainLayout->addItem (mShiftingSpacerRight, 1, 2); 819 pMainLayout->addItem (mShiftingSpacerBottom, 2, 0, 1, -1); 820 } 821 822 mVmPauseAction->setChecked (false); 823 824 CConsole console = mSession.GetConsole(); 825 AssertWrapperOk (mSession); 826 827 CMachine machine = mSession.GetMachine(); 828 829 #ifdef VBOX_WITH_VIDEOHWACCEL 830 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled */ 831 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() 832 && VBoxGlobal::isAcceleration2DVideoAvailable() 833 ; 834 #endif 835 836 mConsole = new VBoxConsoleView (this, console, vboxGlobal().vmRenderMode(), 837 #ifdef VBOX_WITH_VIDEOHWACCEL 838 bAccelerate2DVideo, 839 #endif 840 centralWidget()); 841 qobject_cast <QGridLayout*> (centralWidget()->layout())->addWidget (mConsole, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 842 843 /* Mini toolbar */ 844 bool isActive = !(machine.GetExtraData (VBoxDefs::GUI_ShowMiniToolBar) == "no"); 845 bool isAtTop = (machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAlignment) == "top"); 846 bool isAutoHide = !(machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide) == "off"); 847 QList <QMenu*> menus (QList <QMenu*>() << mVMMenuMini << mDevicesMenu); 848 mMiniToolBar = new VBoxMiniToolBar (centralWidget(), isAtTop ? VBoxMiniToolBar::AlignTop : VBoxMiniToolBar::AlignBottom, 849 isActive, isAutoHide); 850 *mMiniToolBar << menus; 851 connect (mMiniToolBar, SIGNAL (exitAction()), this, SLOT (mtExitMode())); 852 connect (mMiniToolBar, SIGNAL (closeAction()), this, SLOT (mtCloseVM())); 853 connect (mMiniToolBar, SIGNAL (geometryUpdated()), this, SLOT (mtMaskUpdate())); 854 connect (this, SIGNAL (closing()), mMiniToolBar, SLOT (close())); 855 856 activateUICustomizations(); 857 858 /* Set the VM-specific application icon */ 859 /* Not on Mac OS X. The dock icon is handled below. */ 860 #ifndef Q_WS_MAC 861 setWindowIcon (vboxGlobal().vmGuestOSTypeIcon (machine.GetOSTypeId())); 862 #endif 863 864 /* Restore the position of the window and some options */ 865 { 866 QString str = machine.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 867 868 bool ok = false, max = false; 869 int x = 0, y = 0, w = 0, h = 0; 870 x = str.section (',', 0, 0).toInt (&ok); 871 if (ok) 872 y = str.section (',', 1, 1).toInt (&ok); 873 if (ok) 874 w = str.section (',', 2, 2).toInt (&ok); 875 if (ok) 876 h = str.section (',', 3, 3).toInt (&ok); 877 if (ok) 878 max = str.section (',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 879 880 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 881 QApplication::desktop()->availableGeometry (this); 882 883 if (ok /* previous parameters were read correctly */) 884 { 885 mNormalGeo = QRect (x, y, w, h); 886 setGeometry (mNormalGeo); 887 888 /* Normalize to the optimal size */ 889 mConsole->normalizeGeometry (true /* adjustPosition */); 890 891 if (max) 892 { 893 /* Maximize if needed */ 894 setWindowState (windowState() | Qt::WindowMaximized); 895 mWasMax = max; 896 } 897 } 898 else 899 { 900 /* Normalize to the optimal size */ 901 mConsole->normalizeGeometry (true /* adjustPosition */); 902 903 /* Move newly created window to the screen center. */ 904 mNormalGeo = geometry(); 905 mNormalGeo.moveCenter (ar.center()); 906 setGeometry (mNormalGeo); 907 } 908 909 show(); 910 911 /* Process show & possible maximize events */ 912 qApp->processEvents(); 913 914 mVmSeamlessAction->setEnabled (false); 915 str = machine.GetExtraData (VBoxDefs::GUI_Seamless); 916 if (str == "on") 917 mVmSeamlessAction->setChecked (true); 918 919 str = machine.GetExtraData (VBoxDefs::GUI_AutoresizeGuest); 920 if (str != "off") 921 mVmAutoresizeGuestAction->setChecked (true); 922 923 str = machine.GetExtraData (VBoxDefs::GUI_FirstRun); 924 if (str == "yes") 925 mIsFirstTimeStarted = true; 926 else if (!str.isEmpty()) 927 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 928 929 str = machine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime); 930 if (str == "no") 931 mIsAutoSaveMedia = false; 932 933 /* Check if one of extended modes to be activated on loading */ 934 QString fsMode = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 935 QString slMode = machine.GetExtraData (VBoxDefs::GUI_Seamless); 936 bool extendedMode = fsMode == "on" || slMode == "on"; 937 938 /* If one of extended modes to be loaded we have to ignore default 939 * console resize event which will come from VGA Device on loading. */ 940 if (extendedMode) 941 mConsole->requestToResize (QSize (w, h - menuBar()->height() - statusBar()->height())); 942 } 943 944 /* initialize storage stuff */ 945 int cdDevicesCount = 0; 946 int fdDevicesCount = 0; 947 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 948 foreach (const CMediumAttachment &attachment, attachments) 949 { 950 if (attachment.GetType() == KDeviceType_DVD) 951 ++ cdDevicesCount; 952 if (attachment.GetType() == KDeviceType_Floppy) 953 ++ fdDevicesCount; 954 } 955 mDevicesCDMenu->menuAction()->setData (cdDevicesCount); 956 mDevicesFDMenu->menuAction()->setData (fdDevicesCount); 957 mDevicesCDMenu->menuAction()->setVisible (cdDevicesCount); 958 mDevicesFDMenu->menuAction()->setVisible (fdDevicesCount); 959 960 /* initialize usb stuff */ 961 CUSBController usbctl = machine.GetUSBController(); 962 if (usbctl.isNull()) 963 { 964 /* hide usb_menu & usb_separator & usb_status_led */ 965 mDevicesUSBMenu->setVisible (false); 966 mUSBLed->setHidden (true); 967 } 968 else 969 { 970 bool isUSBEnabled = usbctl.GetEnabled(); 971 mDevicesUSBMenu->setEnabled (isUSBEnabled); 972 mDevicesUSBMenu->setConsole (console); 973 mUSBLed->setState (isUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null); 974 } 975 976 /* initialize vrdp stuff */ 977 CVRDPServer vrdpsrv = machine.GetVRDPServer(); 978 if (vrdpsrv.isNull()) 979 { 980 /* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */ 981 mDevicesSwitchVrdpAction->setVisible (false); 982 mDevicesSwitchVrdpSeparator->setVisible (false); 983 #if 0 /* TODO: Allow to setup status-bar! */ 984 mVrdpLed->setHidden (true); 985 #endif 986 } 987 988 /* start an idle timer that will update device lighths */ 989 connect (mIdleTimer, SIGNAL (timeout()), SLOT (updateDeviceLights())); 990 mIdleTimer->start (50); 991 992 connect (mConsole, SIGNAL (mouseStateChanged (int)), this, SLOT (updateMouseState (int))); 993 connect (mConsole, SIGNAL (keyboardStateChanged (int)), mHostkeyLed, SLOT (setState (int))); 994 connect (mConsole, SIGNAL (machineStateChanged (KMachineState)), this, SLOT (updateMachineState (KMachineState))); 995 connect (mConsole, SIGNAL (additionsStateChanged (const QString&, bool, bool, bool)), 996 this, SLOT (updateAdditionsState (const QString &, bool, bool, bool))); 997 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), 998 this, SLOT (updateMediaDriveState (VBoxDefs::MediumType))); 999 connect (mConsole, SIGNAL (usbStateChange()), this, SLOT (updateUsbState())); 1000 connect (mConsole, SIGNAL (networkStateChange()), this, SLOT (updateNetworkAdaptersState())); 1001 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateSharedFoldersState())); 1002 1003 #ifdef Q_WS_MAC 1004 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 1005 /* Default to true if it is an empty value */ 1006 bool f = (testStr.isEmpty() || testStr == "true"); 1007 mConsole->setDockIconEnabled (f); 1008 mConsole->updateDockOverlay(); 1009 #endif 1010 1011 /* set the correct initial mMachineState value */ 1012 mMachineState = console.GetState(); 1013 1014 mConsole->normalizeGeometry (false /* adjustPosition */); 1015 1016 updateAppearanceOf (AllStuff); 1017 1018 if (vboxGlobal().settings().autoCapture()) 1019 vboxProblem().remindAboutAutoCapture(); 1020 1021 /* 1022 * The further startup procedure should be done after we leave this method 1023 * and enter the main event loop in main(), because it may result into 1024 * showing various modal dialogs that will process events from within 1025 * this method that in turn can lead to various side effects like this 1026 * window is closed before this method returns, etc. 1027 */ 1028 1029 QTimer::singleShot (0, this, SLOT (finalizeOpenView())); 1030 1031 LogFlowFuncLeave(); 1032 return true; 1033 } 1034 1035 void VBoxConsoleWnd::setMouseIntegrationLocked (bool aDisabled) 1036 { 1037 mVmDisableMouseIntegrAction->setChecked (false); 1038 mVmDisableMouseIntegrAction->setEnabled (aDisabled); 1039 } 1040 1041 /** 1042 * Shows up and activates the popup version of the main menu. 1043 * 1044 * @param aCenter If @a true, center the popup menu on the screen, otherwise 1045 * show it at the current mouse pointer location. 1046 */ 1047 void VBoxConsoleWnd::popupMainMenu (bool aCenter) 1048 { 1049 QPoint pos = QCursor::pos(); 1050 if (aCenter) 1051 { 1052 QRect deskGeo = QApplication::desktop()->screenGeometry (this); 1053 QRect popGeo = mMainMenu->frameGeometry(); 1054 popGeo.moveCenter (QPoint (deskGeo.width() / 2, deskGeo.height() / 2)); 1055 pos = popGeo.topLeft(); 1056 } 1057 else 1058 { 1059 /* put the menu's bottom right corner to the pointer's hotspot point */ 1060 pos.setX (pos.x() - mMainMenu->frameGeometry().width()); 1061 pos.setY (pos.y() - mMainMenu->frameGeometry().height()); 1062 } 1063 1064 mMainMenu->popup (pos); 1065 mMainMenu->selectFirstAction(); 1066 #ifdef Q_WS_WIN 1067 mMainMenu->activateWindow(); 1068 #endif 1069 } 1070 1071 void VBoxConsoleWnd::installGuestAdditionsFrom (const QString &aSource) 1072 { 1073 CVirtualBox vbox = vboxGlobal().virtualBox(); 1074 QString uuid; 1075 1076 CMedium image = vbox.FindDVDImage (aSource); 1077 if (image.isNull()) 1078 { 1079 image = vbox.OpenDVDImage (aSource, uuid); 1080 if (vbox.isOk()) 1081 uuid = image.GetId(); 1082 } 1083 else 1084 uuid = image.GetId(); 1085 1086 if (!vbox.isOk()) 1087 return vboxProblem().cannotOpenMedium (this, vbox, VBoxDefs::MediumType_DVD, aSource); 1088 1089 Assert (!uuid.isNull()); 1090 CMachine m = mSession.GetMachine(); 1091 1092 QString ctrName; 1093 LONG ctrPort = -1, ctrDevice = -1; 1094 /* Searching for the first suitable slot */ 1095 { 1096 CStorageControllerVector controllers = m.GetStorageControllers(); 1097 int i = 0; 1098 while (i < controllers.size() && ctrName.isNull()) 1099 { 1100 CStorageController controller = controllers [i]; 1101 CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController (controller.GetName()); 1102 int j = 0; 1103 while (j < attachments.size() && ctrName.isNull()) 1104 { 1105 CMediumAttachment attachment = attachments [j]; 1106 if (attachment.GetType() == KDeviceType_DVD) 1107 { 1108 ctrName = controller.GetName(); 1109 ctrPort = attachment.GetPort(); 1110 ctrDevice = attachment.GetDevice(); 1111 } 1112 ++ j; 1113 } 1114 ++ i; 1115 } 1116 } 1117 1118 if (!ctrName.isNull()) 1119 { 1120 bool isMounted = false; 1121 1122 /* Mount medium to the predefined port/device */ 1123 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, false /* force */); 1124 if (m.isOk()) 1125 isMounted = true; 1126 else 1127 { 1128 /* Ask for force mounting */ 1129 if (vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 1130 { 1131 /* Force mount medium to the predefined port/device */ 1132 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, true /* force */); 1133 if (m.isOk()) 1134 isMounted = true; 1135 else 1136 vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, false /* retry? */); 1137 } 1138 } 1139 1140 /* Save medium mounted at runtime */ 1141 if (isMounted && mIsAutoSaveMedia) 1142 { 1143 m.SaveSettings(); 1144 if (!m.isOk()) 1145 vboxProblem().cannotSaveMachineSettings (m); 1146 } 1147 } 1148 else 1149 vboxProblem().cannotMountGuestAdditions (m.GetName()); 1150 } 1151 1152 void VBoxConsoleWnd::setMask (const QRegion &aRegion) 1153 { 1154 QRegion region = aRegion; 1155 1156 /* The global mask shift cause of toolbars and such things. */ 1157 region.translate (mMaskShift.width(), mMaskShift.height()); 1158 1159 /* Including mini toolbar area */ 1160 QRegion toolBarRegion (mMiniToolBar->mask()); 1161 toolBarRegion.translate (mMiniToolBar->mapToGlobal (toolBarRegion.boundingRect().topLeft()) - QPoint (1, 0)); 1162 region += toolBarRegion; 1163 1164 /* Restrict the drawing to the available space on the screen. 1165 * (The &operator is better than the previous used -operator, 1166 * because this excludes space around the real screen also. 1167 * This is necessary for the mac.) */ 1168 region &= mStrictedRegion; 1169 1170 #ifdef Q_WS_WIN 1171 QRegion difference = mPrevRegion.subtract (region); 1172 1173 /* Region offset calculation */ 1174 int fleft = 0, ftop = 0; 1175 1176 /* Visible region calculation */ 1177 HRGN newReg = CreateRectRgn (0, 0, 0, 0); 1178 CombineRgn (newReg, region.handle(), 0, RGN_COPY); 1179 OffsetRgn (newReg, fleft, ftop); 1180 1181 /* Invisible region calculation */ 1182 HRGN diffReg = CreateRectRgn (0, 0, 0, 0); 1183 CombineRgn (diffReg, difference.handle(), 0, RGN_COPY); 1184 OffsetRgn (diffReg, fleft, ftop); 1185 1186 /* Set the current visible region and clean the previous */ 1187 SetWindowRgn (winId(), newReg, FALSE); 1188 RedrawWindow (0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 1189 RedrawWindow (mConsole->viewport()->winId(), 0, 0, RDW_INVALIDATE); 1190 1191 mPrevRegion = region; 1192 #elif defined (Q_WS_MAC) 1193 # if defined (VBOX_GUI_USE_QUARTZ2D) 1194 if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) 1195 { 1196 /* If we are using the Quartz2D backend we have to trigger 1197 * an repaint only. All the magic clipping stuff is done 1198 * in the paint engine. */ 1199 ::darwinWindowInvalidateShape (mConsole->viewport()); 1200 } 1201 else 1202 # endif 1203 { 1204 /* This is necessary to avoid the flicker by an mask update. 1205 * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html 1206 * for the hint. 1207 * There *must* be a better solution. */ 1208 if (!region.isEmpty()) 1209 region |= QRect (0, 0, 1, 1); 1210 // /* Save the current region for later processing in the darwin event handler. */ 1211 // mCurrRegion = region; 1212 // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately 1213 // * this command flushes a copy of the backbuffer to the screen after the new 1214 // * mask is set. This leads into a missplaced drawing of the content. Currently 1215 // * no alternative to this and also this is not 100% perfect. */ 1216 // repaint(); 1217 // qApp->processEvents(); 1218 // /* Now force the reshaping of the window. This is definitly necessary. */ 1219 // ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId())); 1220 QMainWindow::setMask (region); 1221 // HIWindowInvalidateShadow (::darwinToWindowRef (mConsole->viewport())); 1222 } 1223 #else 1224 QMainWindow::setMask (region); 1225 #endif 1226 } 1227 1228 void VBoxConsoleWnd::clearMask() 1229 { 1230 #ifdef Q_WS_WIN 1231 SetWindowRgn (winId(), 0, TRUE); 1232 #else 1233 QMainWindow::clearMask(); 1234 #endif 1235 } 1236 1237 void VBoxConsoleWnd::onDisplayResize (ulong aHeight, ulong aWidth) 1238 { 1239 if (mIsSeamless && QApplication::desktop()->availableGeometry (this).size() != QSize (aHeight, aWidth)) 1240 { 1241 mVmSeamlessAction->setChecked (false); 1242 /* should be cleared already, but just in case */ 1243 if (mIsSeamless) 1244 toggleFullscreenMode (false, true); 1245 } 1246 } 1247 1248 1249 bool VBoxConsoleWnd::event (QEvent *aEvent) 1250 { 1251 switch (aEvent->type()) 1252 { 1253 /* By handling every Resize and Move we keep track of the normal 1254 * (non-minimized and non-maximized) window geometry. Shame on Qt 1255 * that it doesn't provide this geometry in its public APIs. */ 1256 1257 case QEvent::Resize: 1258 { 1259 QResizeEvent *re = (QResizeEvent *) aEvent; 1260 1261 if (!mIsWaitingModeResize && !isWindowMaximized() && 1262 !isTrueFullscreen() && !isTrueSeamless()) 1263 { 1264 mNormalGeo.setSize (re->size()); 1265 #ifdef VBOX_WITH_DEBUGGER_GUI 1266 dbgAdjustRelativePos(); 1267 #endif 1268 } 1269 1270 if (mIsWaitingModeResize) 1271 { 1272 if (!mIsFullscreen && !mIsSeamless) 1273 { 1274 mIsWaitingModeResize = false; 1275 QTimer::singleShot (0, this, SLOT (onExitFullscreen())); 1276 } 1277 } 1278 break; 1279 } 1280 case QEvent::Move: 1281 { 1282 if (!isWindowMaximized() && !isTrueFullscreen() && !isTrueSeamless()) 1283 { 1284 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1285 #ifdef VBOX_WITH_DEBUGGER_GUI 1286 dbgAdjustRelativePos(); 1287 #endif 1288 } 1289 break; 1290 } 1291 #ifdef Q_WS_MAC 1292 case QEvent::Paint: 1293 { 1294 if (mIsSeamless) 1295 { 1296 /* Clear the background */ 1297 CGContextClearRect (::darwinToCGContextRef (this), ::darwinToCGRect (frameGeometry())); 1298 } 1299 break; 1300 } 1301 #endif 1302 case StatusTipEvent::Type: 1303 { 1304 StatusTipEvent *ev = (StatusTipEvent*) aEvent; 1305 statusBar()->showMessage (ev->mTip); 1306 break; 1307 } 1308 default: 1309 break; 1310 } 1311 1312 return QMainWindow::event (aEvent); 1313 } 1314 1315 void VBoxConsoleWnd::closeEvent (QCloseEvent *aEvent) 1316 { 1317 LogFlowFuncEnter(); 1318 1319 static const char *kSave = "save"; 1320 static const char *kShutdown = "shutdown"; 1321 static const char *kPowerOff = "powerOff"; 1322 static const char *kDiscardCurState = "discardCurState"; 1323 1324 if (!mConsole) 1325 { 1326 aEvent->accept(); 1327 LogFlowFunc (("Console already destroyed!")); 1328 LogFlowFuncLeave(); 103 machineWindow()->setWindowTitle(machine.GetName() + strSnapshotName + " [" + 104 vboxGlobal().toString(machineLogic()->machineState()) + "] - " + 105 m_strWindowTitlePrefix); 106 107 // TODO: Move that to fullscreen/seamless update routine: 108 // mMiniToolBar->setDisplayText(machine.GetName() + strSnapshotName); 109 } 110 } 111 112 void UIMachineWindow::closeEvent(QCloseEvent *pEvent) 113 { 114 static const char *pstrSave = "save"; 115 static const char *pstrShutdown = "shutdown"; 116 static const char *pstrPowerOff = "powerOff"; 117 static const char *pstrDiscardCurState = "discardCurState"; 118 119 if (!machineView()) 120 { 121 pEvent->accept(); 1329 122 return; 1330 123 } 1331 124 1332 switch (m MachineState)125 switch (machineLogic()->machineState()) 1333 126 { 1334 127 case KMachineState_PoweredOff: … … 1337 130 case KMachineState_Aborted: 1338 131 /* The machine has been already powered off or saved or aborted -- close the window immediately. */ 1339 aEvent->accept();132 pEvent->accept(); 1340 133 break; 1341 134 1342 135 default: 1343 136 /* The machine is in some temporary state like Saving or Stopping. 1344 * Ignore the close event. When it is Stopping, it will be soon closed anyway from updateMachineState().137 * Ignore the close event. When it is Stopping, it will be soon closed anyway from sltUpdatmachineState(). 1345 138 * In all other cases, an appropriate progress dialog will be shown within a few seconds. */ 1346 aEvent->ignore();1347 break; 1348 1349 case KMachineState_Teleporting: 139 pEvent->ignore(); 140 break; 141 142 case KMachineState_Teleporting: /** @todo Live Migration: Test closing a VM that's being teleported or snapshotted. */ 1350 143 case KMachineState_LiveSnapshotting: 1351 144 case KMachineState_Running: … … 1354 147 case KMachineState_Stuck: 1355 148 /* Start with ignoring the close event */ 1356 aEvent->ignore();1357 1358 bool isACPIEnabled = m Session.GetConsole().GetGuestEnteredACPIMode();149 pEvent->ignore(); 150 151 bool isACPIEnabled = machineLogic()->session().GetConsole().GetGuestEnteredACPIMode(); 1359 152 1360 153 bool success = true; 1361 154 1362 bool wasPaused = m MachineState == KMachineState_Paused1363 || mMachineState == KMachineState_Stuck1364 || mMachineState== KMachineState_TeleportingPausedVM;155 bool wasPaused = machineLogic()->machineState() == KMachineState_Paused || 156 machineLogic()->machineState() == KMachineState_Stuck || 157 machineLogic()->machineState() == KMachineState_TeleportingPausedVM; 1365 158 if (!wasPaused) 1366 159 { 1367 160 /* Suspend the VM and ignore the close event if failed to do so. 1368 161 * pause() will show the error message to the user. */ 1369 success = m Console->pause(true);162 success = machineLogic()->pause(true); 1370 163 } 1371 164 … … 1374 167 success = false; 1375 168 1376 CMachine machine = m Session.GetMachine();1377 VBoxCloseVMDlg dlg (this);169 CMachine machine = machineLogic()->session().GetMachine(); 170 VBoxCloseVMDlg dlg(machineWindow()); 1378 171 QString typeId = machine.GetOSTypeId(); 1379 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon(typeId));172 dlg.pmIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(typeId)); 1380 173 1381 174 /* Make the Discard checkbox invisible if there are no snapshots */ 1382 dlg.mCbDiscardCurState->setVisible 175 dlg.mCbDiscardCurState->setVisible(machine.GetSnapshotCount() > 0); 1383 176 if (!machine.GetCurrentSnapshot().isNull()) 1384 dlg.mCbDiscardCurState->setText (dlg.mCbDiscardCurState->text().arg(machine.GetCurrentSnapshot().GetName()));1385 1386 if (m MachineState!= KMachineState_Stuck)177 dlg.mCbDiscardCurState->setText(dlg.mCbDiscardCurState->text().arg(machine.GetCurrentSnapshot().GetName())); 178 179 if (machineLogic()->machineState() != KMachineState_Stuck) 1387 180 { 1388 181 /* Read the last user's choice for the given VM */ 1389 QStringList lastAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split(',');1390 AssertWrapperOk 1391 if (lastAction [0] == kSave)1392 { 1393 dlg.mRbShutdown->setEnabled 1394 dlg.mRbSave->setChecked 182 QStringList lastAction = machine.GetExtraData(VBoxDefs::GUI_LastCloseAction).split(','); 183 AssertWrapperOk(machine); 184 if (lastAction[0] == pstrSave) 185 { 186 dlg.mRbShutdown->setEnabled(isACPIEnabled); 187 dlg.mRbSave->setChecked(true); 1395 188 dlg.mRbSave->setFocus(); 1396 189 } 1397 else if (lastAction [0] == kPowerOff || !isACPIEnabled)1398 { 1399 dlg.mRbShutdown->setEnabled 1400 dlg.mRbPowerOff->setChecked 190 else if (lastAction[0] == pstrPowerOff || !isACPIEnabled) 191 { 192 dlg.mRbShutdown->setEnabled(isACPIEnabled); 193 dlg.mRbPowerOff->setChecked(true); 1401 194 dlg.mRbPowerOff->setFocus(); 1402 195 } 1403 196 else /* The default is ACPI Shutdown */ 1404 197 { 1405 dlg.mRbShutdown->setChecked 198 dlg.mRbShutdown->setChecked(true); 1406 199 dlg.mRbShutdown->setFocus(); 1407 200 } 1408 dlg.mCbDiscardCurState->setChecked (lastAction.count() > 1 && lastAction [1] == kDiscardCurState);201 dlg.mCbDiscardCurState->setChecked(lastAction.count() > 1 && lastAction [1] == pstrDiscardCurState); 1409 202 } 1410 203 else 1411 204 { 1412 205 /* The stuck VM can only be powered off; disable anything else and choose PowerOff */ 1413 dlg.mRbSave->setEnabled 1414 dlg.mRbShutdown->setEnabled 1415 dlg.mRbPowerOff->setChecked 206 dlg.mRbSave->setEnabled(false); 207 dlg.mRbShutdown->setEnabled(false); 208 dlg.mRbPowerOff->setChecked(true); 1416 209 } 1417 210 … … 1422 215 /* Disable auto closure because we want to have a chance to show 1423 216 * the error dialog on save state / power off failure. */ 1424 mNoAutoClose = true; 1425 1426 CConsole console = mConsole->console(); 217 // TODO: process for multiple windows! 218 //m_bNoAutoClose = true; 219 220 CConsole console = machineLogic()->session().GetConsole(); 1427 221 1428 222 if (dlg.mRbSave->isChecked()) … … 1433 227 { 1434 228 /* Show the "VM saving" progress dialog */ 1435 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0);229 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindow(), 0); 1436 230 if (progress.GetResultCode() != 0) 1437 vboxProblem().cannotSaveMachineState 231 vboxProblem().cannotSaveMachineState(progress); 1438 232 else 1439 233 success = true; 1440 234 } 1441 235 else 1442 vboxProblem().cannotSaveMachineState 236 vboxProblem().cannotSaveMachineState(console); 1443 237 } 1444 238 else if (dlg.mRbShutdown->isChecked()) 1445 239 { 1446 240 /* Unpause the VM to let it grab the ACPI shutdown event */ 1447 m Console->pause(false);241 machineLogic()->pause(false); 1448 242 /* Prevent the subsequent unpause request */ 1449 243 wasPaused = true; … … 1453 247 wasShutdown = console.isOk(); 1454 248 if (!wasShutdown) 1455 vboxProblem().cannotACPIShutdownMachine 249 vboxProblem().cannotACPIShutdownMachine(console); 1456 250 /* Success is always false because we never accept the close 1457 251 * window action when doing ACPI shutdown */ … … 1465 259 { 1466 260 /* Show the power down progress dialog */ 1467 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this);261 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindow()); 1468 262 if (progress.GetResultCode() != 0) 1469 vboxProblem().cannotStopMachine 263 vboxProblem().cannotStopMachine(progress); 1470 264 else 1471 265 success = true; 1472 266 } 1473 267 else 1474 vboxProblem().cannotStopMachine 268 vboxProblem().cannotStopMachine(console); 1475 269 1476 270 if (success) … … 1481 275 1482 276 /* Discard the current state if requested */ 1483 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo 277 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo(&dlg)) 1484 278 { 1485 279 CSnapshot snapshot = machine.GetCurrentSnapshot(); 1486 CProgress progress = console.RestoreSnapshot 280 CProgress progress = console.RestoreSnapshot(snapshot); 1487 281 if (console.isOk()) 1488 282 { 1489 283 /* Show the progress dialog */ 1490 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this);284 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindow()); 1491 285 if (progress.GetResultCode() != 0) 1492 vboxProblem().cannotRestoreSnapshot 286 vboxProblem().cannotRestoreSnapshot(progress, snapshot.GetName()); 1493 287 } 1494 288 else 1495 vboxProblem().cannotRestoreSnapshot 289 vboxProblem().cannotRestoreSnapshot(console, snapshot.GetName()); 1496 290 } 1497 291 } … … 1501 295 { 1502 296 /* Accept the close action on success */ 1503 aEvent->accept();297 pEvent->accept(); 1504 298 } 1505 299 … … 1507 301 { 1508 302 /* Read the last user's choice for the given VM */ 1509 QStringList prevAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split(',');303 QStringList prevAction = machine.GetExtraData(VBoxDefs::GUI_LastCloseAction).split(','); 1510 304 /* Memorize the last user's choice for the given VM */ 1511 QString lastAction = kPowerOff;305 QString lastAction = pstrPowerOff; 1512 306 if (dlg.mRbSave->isChecked()) 1513 lastAction = kSave;307 lastAction = pstrSave; 1514 308 else if (dlg.mRbShutdown->isChecked() || 1515 (dlg.mRbPowerOff->isChecked() && prevAction [0] == kShutdown && !isACPIEnabled))1516 lastAction = kShutdown;309 (dlg.mRbPowerOff->isChecked() && prevAction [0] == pstrShutdown && !isACPIEnabled)) 310 lastAction = pstrShutdown; 1517 311 else if (dlg.mRbPowerOff->isChecked()) 1518 lastAction = kPowerOff;312 lastAction = pstrPowerOff; 1519 313 else 1520 314 AssertFailed(); 1521 315 if (dlg.mCbDiscardCurState->isChecked()) 1522 (lastAction += ",") += kDiscardCurState;316 (lastAction += ",") += pstrDiscardCurState; 1523 317 machine.SetExtraData (VBoxDefs::GUI_LastCloseAction, lastAction); 1524 AssertWrapperOk 318 AssertWrapperOk(machine); 1525 319 } 1526 320 } 1527 321 } 1528 322 1529 mNoAutoClose = false;1530 1531 if ( mMachineState == KMachineState_PoweredOff 1532 || mMachineState == KMachineState_Saved1533 || mMachineState == KMachineState_Teleported1534 || mMachineState == KMachineState_Aborted1535 )323 // TODO: process for multiple windows! 324 //m_bNoAutoClose = false; 325 326 if (machineLogic()->machineState() == KMachineState_PoweredOff || 327 machineLogic()->machineState() == KMachineState_Saved || 328 machineLogic()->machineState() == KMachineState_Teleported || 329 machineLogic()->machineState() == KMachineState_Aborted) 1536 330 { 1537 331 /* The machine has been stopped while showing the Close or the Pause 1538 332 * failure dialog -- accept the close event immediately. */ 1539 aEvent->accept();333 pEvent->accept(); 1540 334 } 1541 335 else … … 1544 338 { 1545 339 /* Restore the running state if needed */ 1546 if (!wasPaused && m MachineState== KMachineState_Paused)1547 m Console->pause(false);340 if (!wasPaused && machineLogic()->machineState() == KMachineState_Paused) 341 machineLogic()->pause(false); 1548 342 } 1549 343 } … … 1551 345 } 1552 346 1553 if ( aEvent->isAccepted())347 if (pEvent->isAccepted()) 1554 348 { 1555 349 #ifndef VBOX_GUI_SEPARATE_VM_PROCESS … … 1557 351 #endif 1558 352 1559 /* Stop LED update timer */1560 mIdleTimer->stop();1561 mIdleTimer->disconnect (SIGNAL (timeout()), this, SLOT (updateDeviceLights()));1562 1563 353 /* Hide console window */ 1564 hide(); 1565 1566 /* Save the position of the window and some options */ 1567 CMachine machine = mSession.GetMachine(); 1568 QString winPos = QString ("%1,%2,%3,%4") 1569 .arg (mNormalGeo.x()).arg (mNormalGeo.y()) 1570 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 1571 if (isWindowMaximized() || (mIsFullscreen && mWasMax) || (mIsSeamless && mWasMax)) 1572 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowPosition_Max); 1573 1574 machine.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 1575 1576 machine.SetExtraData (VBoxDefs::GUI_Fullscreen, 1577 mVmFullscreenAction->isChecked() ? "on" : "off"); 1578 machine.SetExtraData (VBoxDefs::GUI_Seamless, 1579 mVmSeamlessAction->isChecked() ? "on" : "off"); 1580 machine.SetExtraData (VBoxDefs::GUI_AutoresizeGuest, 1581 mVmAutoresizeGuestAction->isChecked() ? "on" : "off"); 1582 machine.SetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide, 1583 mMiniToolBar->isAutoHide() ? "on" : "off"); 354 machineWindow()->hide(); 1584 355 1585 356 #ifdef VBOX_WITH_DEBUGGER_GUI 1586 357 /* Close & destroy the debugger GUI */ 1587 dbgDestroy(); 358 // TODO: Check that logic! 359 //dbgDestroy(); 1588 360 #endif 1589 361 … … 1592 364 1593 365 /* Notify all the top-level dialogs about closing */ 1594 emit closing(); 1595 } 1596 1597 LogFlowFunc (("accepted=%d\n", aEvent->isAccepted())); 1598 LogFlowFuncLeave(); 1599 } 1600 1601 #ifdef Q_WS_X11 1602 bool VBoxConsoleWnd::x11Event (XEvent *aEvent) 1603 { 1604 /* Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut, 1605 * WindowActivate and WindowDeactivate Qt events are not properly sent 1606 * on top level window (i.e. this) deactivation. The fix is to substiute 1607 * the mode in FocusOut X11 event structure to NotifyNormal to cause 1608 * Qt to process it as desired. */ 1609 if (mConsole && aEvent->type == FocusOut) 1610 { 1611 if (aEvent->xfocus.mode == NotifyWhileGrabbed && 1612 (aEvent->xfocus.detail == NotifyAncestor || 1613 aEvent->xfocus.detail == NotifyInferior || 1614 aEvent->xfocus.detail == NotifyNonlinear)) 1615 { 1616 aEvent->xfocus.mode = NotifyNormal; 1617 } 1618 } 1619 return false; 1620 } 1621 #endif 1622 1623 /** 1624 * Sets the strings of the subwidgets using the current 1625 * language. 1626 */ 1627 void VBoxConsoleWnd::retranslateUi() 1628 { 1629 #ifdef VBOX_OSE 1630 mCaptionPrefix = tr ("VirtualBox OSE"); 1631 #else 1632 mCaptionPrefix = tr ("Sun VirtualBox"); 1633 #endif 1634 1635 #ifdef VBOX_BLEEDING_EDGE 1636 mCaptionPrefix += tr (" EXPERIMENTAL build %1r%2 - %3").arg (RTBldCfgVersion()).arg (RTBldCfgRevisionStr()).arg (VBOX_BLEEDING_EDGE); 1637 #endif 1638 /* 1639 * Note: All action shortcuts should be added to the menu text in the 1640 * form of "\tHost+<Key>" where <Key> is the shortcut key according 1641 * to regular QKeySequence rules. No translation of the "Host" word is 1642 * allowed (VBoxConsoleView relies on its spelling). setAccel() must not 1643 * be used. Unfortunately on the Mac the "host" string is silently removed 1644 * & the key is created as an global shortcut. So every e.g. F key stroke 1645 * in the vm leads to a menu call of the F entry. Mysteriously the 1646 * associated action isn't started. As a workaround the Host+<key> is 1647 * written in braces after the menu text. 1648 */ 1649 1650 /* VM actions */ 366 // TODO: Notify about closing! 367 // emit closing(); 368 } 369 } 370 371 void UIMachineWindow::prepareWindowIcon() 372 { 373 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 374 /* The default application icon (will be changed to VM-specific icon little bit later): 375 * 1. On Win32, it's built-in to the executable; 376 * 2. On Mac OS X the icon referenced in info.plist is used. */ 377 machineWindow()->setWindowIcon(QIcon(":/VirtualBox_48px.png")); 378 #endif 379 380 #ifndef Q_WS_MAC 381 /* Set the VM-specific application icon except Mac OS X: */ 382 CMachine machine = machineLogic()->session().GetMachine(); 383 machineWindow()->setWindowIcon(vboxGlobal().vmGuestOSTypeIcon(machine.GetOSTypeId())); 384 #endif 385 } 386 387 void UIMachineWindow::loadWindowSettings() 388 { 1651 389 #ifdef Q_WS_MAC 1652 qt_set_sequence_auto_mnemonic (false); 1653 #endif 1654 1655 mVmDisMouseIntegrMenu->setToolTip (tr ("Mouse Integration", "enable/disable...")); 1656 #if 0 /* TODO: Allow to setup status-bar! */ 1657 mVmAutoresizeMenu->setToolTip (tr ("Auto-resize Guest Display", "enable/disable...")); 1658 #endif 1659 1660 mVmFullscreenAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Fullscreen Mode"), "F")); 1661 mVmFullscreenAction->setStatusTip (tr ("Switch to fullscreen mode" )); 1662 1663 mVmSeamlessAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Seam&less Mode"), "L")); 1664 mVmSeamlessAction->setStatusTip (tr ("Switch to seamless desktop integration mode")); 1665 1666 mVmAutoresizeGuestAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Auto-resize &Guest Display"), "G")); 1667 mVmAutoresizeGuestAction->setStatusTip (tr ("Automatically resize the guest display when the " 1668 "window is resized (requires Guest Additions)")); 1669 1670 mVmAdjustWindowAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Adjust Window Size"), "A")); 1671 mVmAdjustWindowAction->setStatusTip (tr ("Adjust window size and position to best fit the guest display")); 1672 1673 /* mVmDisableMouseIntegrAction is set up in updateAppearanceOf() */ 1674 1675 mVmTypeCADAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Del"), "Del")); 1676 mVmTypeCADAction->setStatusTip (tr ("Send the Ctrl-Alt-Del sequence to the virtual machine")); 1677 1678 #if defined(Q_WS_X11) 1679 mVmTypeCABSAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Backspace"), "Backspace")); 1680 mVmTypeCABSAction->setStatusTip (tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine")); 1681 #endif 1682 1683 mVmTakeSnapshotAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Take &Snapshot..."), "S")); 1684 mVmTakeSnapshotAction->setStatusTip (tr ("Take a snapshot of the virtual machine")); 1685 1686 mVmShowInformationDlgAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Session I&nformation Dialog"), "N")); 1687 mVmShowInformationDlgAction->setStatusTip (tr ("Show Session Information Dialog")); 1688 1689 mVmResetAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Reset"), "R")); 1690 mVmResetAction->setStatusTip (tr ("Reset the virtual machine")); 1691 1692 /* mVmPauseAction is set up in updateAppearanceOf() */ 1693 1694 #ifdef Q_WS_MAC 1695 /* Host+H is Hide on the mac */ 1696 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "U")); 1697 #else /* Q_WS_MAC */ 1698 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "H")); 1699 #endif /* !Q_WS_MAC */ 1700 mVmACPIShutdownAction->setStatusTip (tr ("Send the ACPI Power Button press event to the virtual machine")); 1701 1702 mVmCloseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Close..." ), "Q")); 1703 mVmCloseAction->setStatusTip (tr ("Close the virtual machine")); 1704 mVmCloseAction->setMenuRole (QAction::QuitRole); 1705 1706 /* Devices actions */ 1707 mDevicesCDMenu->setTitle (tr ("&CD/DVD Devices")); 1708 mDevicesFDMenu->setTitle (tr ("&Floppy Devices")); 1709 1710 mDevicesNetworkDialogAction->setText (tr ("&Network Adapters...")); 1711 mDevicesNetworkDialogAction->setStatusTip (tr ("Change the settings of network adapters")); 1712 1713 mDevicesSFDialogAction->setText (tr ("&Shared Folders...")); 1714 mDevicesSFDialogAction->setStatusTip (tr ("Create or modify shared folders")); 1715 1716 mDevicesSwitchVrdpAction->setText (tr ("&Remote Display")); 1717 mDevicesSwitchVrdpAction->setStatusTip (tr ("Enable or disable remote desktop (RDP) connections to this machine")); 1718 #if 0 /* TODO: Allow to setup status-bar! */ 1719 mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server", "enable/disable...")); 1720 #endif 1721 1722 mDevicesInstallGuestToolsAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Install Guest Additions..."), "D")); 1723 mDevicesInstallGuestToolsAction->setStatusTip (tr ("Mount the Guest Additions installation image")); 1724 1725 mDevicesUSBMenu->setTitle (tr ("&USB Devices")); 1726 1727 #ifdef VBOX_WITH_DEBUGGER_GUI 1728 /* Debug actions */ 1729 if (mDbgStatisticsAction) 1730 mDbgStatisticsAction->setText (tr ("&Statistics...", "debug action")); 1731 if (mDbgCommandLineAction) 1732 mDbgCommandLineAction->setText (tr ("&Command Line...", "debug action")); 1733 if (mDbgLoggingAction) 1734 mDbgLoggingAction->setText (tr ("&Logging...", "debug action")); 1735 #endif 1736 1737 /* Help actions */ 1738 mHelpActions.retranslateUi(); 1739 1740 /* Main menu & seamless popup menu */ 1741 mVMMenu->setTitle (tr ("&Machine")); 1742 // mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png")); 1743 1744 mVMMenuMini->setTitle (tr ("&Machine")); 1745 1746 mDevicesMenu->setTitle (tr ("&Devices")); 1747 // mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png")); 1748 1749 #ifdef VBOX_WITH_DEBUGGER_GUI 1750 if (vboxGlobal().isDebuggerEnabled()) 1751 mDbgMenu->setTitle (tr ("De&bug")); 1752 #endif 1753 mHelpMenu->setTitle (tr ("&Help")); 1754 // mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png")); 1755 1756 /* Status bar widgets */ 1757 mMouseLed->setToolTip ( 1758 tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>" 1759 "<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>" 1760 "<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>" 1761 "<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>" 1762 "<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>" 1763 "<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>" 1764 "Note that the mouse integration feature requires Guest Additions to be installed in the guest OS.")); 1765 mHostkeyLed->setToolTip ( 1766 tr ("Indicates whether the keyboard is captured by the guest OS " 1767 "(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>).")); 1768 mHostkeyName->setToolTip ( 1769 tr ("Shows the currently assigned Host key.<br>" 1770 "This key, when pressed alone, toggles the keyboard and mouse " 1771 "capture state. It can also be used in combination with other keys " 1772 "to quickly perform actions from the main menu.")); 1773 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 1774 1775 #if 0 /* TODO: Allow to setup status-bar! */ 1776 mAutoresizeLed->setToolTip ( 1777 tr ("Indicates whether the guest display auto-resize function is On " 1778 "(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). " 1779 "Note that this function requires Guest Additions to be installed in the guest OS.")); 1780 #endif 1781 1782 updateAppearanceOf (AllStuff); 1783 } 1784 1785 void VBoxConsoleWnd::finalizeOpenView() 1786 { 1787 LogFlowFuncEnter(); 1788 1789 /* Notify the console scroll-view about the console-window is opened. */ 1790 mConsole->onViewOpened(); 1791 1792 bool saved = mMachineState == KMachineState_Saved; 1793 1794 CMachine machine = mSession.GetMachine(); 1795 CConsole console = mConsole->console(); 1796 1797 if (mIsFirstTimeStarted) 1798 { 1799 UIFirstRunWzd wzd (this, machine); 1800 wzd.exec(); 1801 1802 /* Remove GUI_FirstRun extra data key from the machine settings 1803 * file after showing the wizard once. */ 1804 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 1805 } 1806 1807 /* Start the VM */ 1808 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 1809 console.PowerUpPaused() : console.PowerUp(); 1810 1811 /* Check for an immediate failure */ 1812 if (!console.isOk()) 1813 { 1814 vboxProblem().cannotStartMachine (console); 1815 /* close this window (this will call closeView()) */ 1816 close(); 1817 1818 LogFlowFunc (("Error starting VM\n")); 1819 LogFlowFuncLeave(); 1820 return; 1821 } 1822 1823 mConsole->attach(); 1824 1825 /* Disable auto closure because we want to have a chance to show the 1826 * error dialog on startup failure */ 1827 mNoAutoClose = true; 1828 1829 /* show the "VM starting / restoring" progress dialog */ 1830 1831 if (saved) 1832 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1833 else 1834 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1835 1836 if (progress.GetResultCode() != 0) 1837 { 1838 vboxProblem().cannotStartMachine (progress); 1839 /* close this window (this will call closeView()) */ 1840 close(); 1841 1842 LogFlowFunc (("Error starting VM\n")); 1843 LogFlowFuncLeave(); 1844 return; 1845 } 1846 1847 mNoAutoClose = false; 1848 1849 /* Check if we missed a really quick termination after successful 1850 * startup, and process it if we did. */ 1851 if ( mMachineState == KMachineState_PoweredOff 1852 || mMachineState == KMachineState_Saved 1853 || mMachineState == KMachineState_Teleported 1854 || mMachineState == KMachineState_Aborted 1855 ) 1856 { 1857 close(); 1858 LogFlowFuncLeave(); 1859 return; 1860 } 1861 1862 /* Currently the machine is started and the guest API could be used... 1863 * Checking if the fullscreen mode should be activated */ 1864 QString str = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 1865 if (str == "on") 1866 mVmFullscreenAction->setChecked (true); 1867 1868 /* If seamless mode should be enabled then check if it is enabled 1869 * currently and re-enable it if seamless is supported */ 1870 if (mVmSeamlessAction->isChecked() && mIsSeamlessSupported && mIsGraphicsSupported) 1871 toggleFullscreenMode (true, true); 1872 #ifdef VBOX_WITH_DEBUGGER_GUI 1873 /* Open the debugger in "full screen" mode requested by the user. */ 1874 else if (vboxGlobal().isDebuggerAutoShowEnabled()) 1875 { 1876 /* console in upper left corner of the desktop. */ 1877 QRect rct (0, 0, 0, 0); 1878 QDesktopWidget *desktop = QApplication::desktop(); 1879 if (desktop) 1880 rct = desktop->availableGeometry(pos()); 1881 move (QPoint (rct.x(), rct.y())); 1882 1883 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled()) 1884 dbgShowStatistics(); 1885 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled()) 1886 dbgShowCommandLine(); 1887 1888 if (!vboxGlobal().isStartPausedEnabled()) 1889 mConsole->pause (false); 1890 } 1891 #endif 1892 1893 mIsOpenViewFinished = true; 1894 LogFlowFuncLeave(); 1895 1896 #ifdef VBOX_WITH_UPDATE_REQUEST 1897 vboxGlobal().showUpdateDialog (false /* aForce */); 1898 #endif 1899 1900 /* Finally check the status of required features. */ 1901 checkRequiredFeatures(); 1902 1903 /* Re-request all the static values finally after 1904 * view is really opened and attached. */ 1905 updateAppearanceOf (VirtualizationStuff); 1906 } 1907 1908 /** 1909 * Helper to safely close the main console window. 1910 * 1911 * This method ensures that close() will not be called if there is some 1912 * modal widget currently being executed, as it can cause uninitialization 1913 * at the point of code where it is not expected at all (example: 1914 * VBoxConsoleView::mouseEvent() calling 1915 * VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to 1916 * close the current modal widget is done and tryClose() is rescheduled for 1917 * later execution using a single-shot zero timer. 1918 * 1919 * In particular, this method is used by updateMachineState() when the VM 1920 * goes offline, which can even happen if we are inside the modal event loop, 1921 * (for example, the VM has been externally powered off or the guest OS 1922 * has initiated a shutdown procedure). 1923 */ 1924 void VBoxConsoleWnd::tryClose() 1925 { 1926 /* First close any open modal & popup widgets. Use a single shot with 1927 * timeout 0 to allow the widgets to cleany close and test then again. If 1928 * all open widgets are closed destroy ourself. */ 1929 QWidget *widget = QApplication::activeModalWidget() ? 1930 QApplication::activeModalWidget() : 1931 QApplication::activePopupWidget() ? 1932 QApplication::activePopupWidget() : 0; 1933 if (widget) 1934 { 1935 widget->close(); 1936 QTimer::singleShot (0, this, SLOT (tryClose())); 1937 } 1938 else 1939 close(); 1940 } 1941 1942 void VBoxConsoleWnd::vmFullscreen (bool aOn) 1943 { 1944 bool ok = toggleFullscreenMode (aOn, false /* aSeamless */); 1945 if (!ok) 1946 { 1947 /* On failure, restore the previous button state */ 1948 mVmFullscreenAction->blockSignals (true); 1949 mVmFullscreenAction->setChecked (!aOn); 1950 mVmFullscreenAction->blockSignals (false); 1951 } 1952 } 1953 1954 void VBoxConsoleWnd::vmSeamless (bool aOn) 1955 { 1956 /* Check if it is possible to enter/leave seamless mode */ 1957 if ((mIsSeamlessSupported && mIsGraphicsSupported) || !aOn) 1958 { 1959 bool ok = toggleFullscreenMode (aOn, true /* aSeamless */); 1960 if (!ok) 1961 { 1962 /* On failure, restore the previous button state */ 1963 mVmSeamlessAction->blockSignals (true); 1964 mVmSeamlessAction->setChecked (!aOn); 1965 mVmSeamlessAction->blockSignals (false); 1966 } 1967 } 1968 } 1969 1970 void VBoxConsoleWnd::vmAutoresizeGuest (bool on) 1971 { 1972 if (!mConsole) 1973 return; 1974 1975 #if 0 /* TODO: Allow to setup status-bar! */ 1976 mAutoresizeLed->setState (on ? 3 : 1); 1977 #endif 1978 1979 mConsole->setAutoresizeGuest (on); 1980 } 1981 1982 void VBoxConsoleWnd::vmAdjustWindow() 1983 { 1984 if (mConsole) 1985 { 1986 if (isWindowMaximized()) 1987 showNormal(); 1988 mConsole->normalizeGeometry (true /* adjustPosition */); 1989 } 1990 } 1991 1992 void VBoxConsoleWnd::vmDisableMouseIntegration (bool aOff) 1993 { 1994 if (mConsole) 1995 { 1996 mConsole->setMouseIntegrationEnabled (!aOff); 1997 updateAppearanceOf (DisableMouseIntegrAction); 1998 } 1999 } 2000 2001 void VBoxConsoleWnd::vmTypeCAD() 2002 { 2003 if (mConsole) 2004 { 2005 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2006 Assert (!keyboard.isNull()); 2007 keyboard.PutCAD(); 2008 AssertWrapperOk (keyboard); 2009 } 2010 } 2011 2012 #ifdef Q_WS_X11 2013 void VBoxConsoleWnd::vmTypeCABS() 2014 { 2015 if (mConsole) 2016 { 2017 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2018 Assert (!keyboard.isNull()); 2019 static QVector <LONG> sSequence (6); 2020 sSequence[0] = 0x1d; // Ctrl down 2021 sSequence[1] = 0x38; // Alt down 2022 sSequence[2] = 0x0E; // Backspace down 2023 sSequence[3] = 0x8E; // Backspace up 2024 sSequence[4] = 0xb8; // Alt up 2025 sSequence[5] = 0x9d; // Ctrl up 2026 keyboard.PutScancodes (sSequence); 2027 AssertWrapperOk (keyboard); 2028 } 2029 } 2030 #endif 2031 2032 void VBoxConsoleWnd::vmTakeSnapshot() 2033 { 2034 AssertReturn (mConsole, (void) 0); 2035 2036 /* remember the paused state */ 2037 bool wasPaused = mMachineState == KMachineState_Paused; 2038 if (!wasPaused) 2039 { 2040 /* Suspend the VM and ignore the close event if failed to do so. 2041 * pause() will show the error message to the user. */ 2042 if (!mConsole->pause (true)) 2043 return; 2044 } 2045 2046 CMachine machine = mSession.GetMachine(); 2047 2048 VBoxTakeSnapshotDlg dlg (this, machine); 2049 2050 QString typeId = machine.GetOSTypeId(); 2051 dlg.mLbIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 2052 2053 /* search for the max available filter index */ 2054 QString nameTemplate = tr ("Snapshot %1"); 2055 int maxSnapshotIndex = searchMaxSnapshotIndex (machine, machine.GetSnapshot (QString()), nameTemplate); 2056 dlg.mLeName->setText (nameTemplate.arg (++ maxSnapshotIndex)); 2057 2058 if (dlg.exec() == QDialog::Accepted) 2059 { 2060 CConsole console = mSession.GetConsole(); 2061 2062 CProgress progress = console.TakeSnapshot (dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 2063 2064 if (console.isOk()) 2065 { 2066 /* Show the "Taking Snapshot" progress dialog */ 2067 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 2068 2069 if (progress.GetResultCode() != 0) 2070 vboxProblem().cannotTakeSnapshot (progress); 2071 } 2072 else 2073 vboxProblem().cannotTakeSnapshot (console); 2074 } 2075 2076 /* Restore the running state if needed */ 2077 if (!wasPaused) 2078 mConsole->pause (false); 2079 } 2080 2081 void VBoxConsoleWnd::vmShowInfoDialog() 2082 { 2083 VBoxVMInformationDlg::createInformationDlg (mSession, mConsole); 2084 } 2085 2086 void VBoxConsoleWnd::vmReset() 2087 { 2088 if (mConsole) 2089 { 2090 if (vboxProblem().confirmVMReset (this)) 2091 mConsole->console().Reset(); 2092 } 2093 } 2094 2095 void VBoxConsoleWnd::vmPause (bool aOn) 2096 { 2097 if (mConsole) 2098 { 2099 mConsole->pause (aOn); 2100 updateAppearanceOf (PauseAction); 2101 } 2102 } 2103 2104 void VBoxConsoleWnd::vmACPIShutdown() 2105 { 2106 if (!mSession.GetConsole().GetGuestEnteredACPIMode()) 2107 return vboxProblem().cannotSendACPIToMachine(); 2108 2109 if (mConsole) 2110 { 2111 CConsole console = mConsole->console(); 2112 console.PowerButton(); 2113 if (!console.isOk()) 2114 vboxProblem().cannotACPIShutdownMachine (console); 2115 } 2116 } 2117 2118 void VBoxConsoleWnd::vmClose() 2119 { 2120 if (mConsole) 2121 close(); 2122 } 2123 2124 void VBoxConsoleWnd::devicesSwitchVrdp (bool aOn) 2125 { 2126 if (!mConsole) return; 2127 2128 CVRDPServer vrdpServer = mSession.GetMachine().GetVRDPServer(); 2129 /* This method should not be executed if vrdpServer is null */ 2130 Assert (!vrdpServer.isNull()); 2131 2132 vrdpServer.SetEnabled (aOn); 2133 updateAppearanceOf (VRDPStuff); 2134 } 2135 2136 void VBoxConsoleWnd::devicesOpenNetworkDialog() 2137 { 2138 if (!mConsole) return; 2139 2140 VBoxNetworkDialog dlg (mConsole, mSession); 2141 dlg.exec(); 2142 } 2143 2144 void VBoxConsoleWnd::devicesOpenSFDialog() 2145 { 2146 if (!mConsole) return; 2147 2148 VBoxSFDialog dlg (mConsole, mSession); 2149 dlg.exec(); 2150 } 2151 2152 void VBoxConsoleWnd::devicesInstallGuestAdditions() 2153 { 2154 char szAppPrivPath [RTPATH_MAX]; 2155 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); 2156 AssertRC (rc); 2157 2158 QString src1 = QString (szAppPrivPath) + "/VBoxGuestAdditions.iso"; 2159 QString src2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 2160 2161 /* Check the standard image locations */ 2162 if (QFile::exists (src1)) 2163 return installGuestAdditionsFrom (src1); 2164 else if (QFile::exists (src2)) 2165 return installGuestAdditionsFrom (src2); 2166 2167 /* Check for the already registered image */ 2168 CVirtualBox vbox = vboxGlobal().virtualBox(); 2169 QString name = QString ("VBoxGuestAdditions_%1.iso").arg (vbox.GetVersion().remove ("_OSE")); 2170 2171 CMediumVector vec = vbox.GetDVDImages(); 2172 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 2173 { 2174 QString path = it->GetLocation(); 2175 /* Compare the name part ignoring the file case */ 2176 QString fn = QFileInfo (path).fileName(); 2177 if (RTPathCompare (name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 2178 return installGuestAdditionsFrom (path); 2179 } 2180 2181 /* Download the required image */ 2182 int result = vboxProblem().cannotFindGuestAdditions ( 2183 QDir::toNativeSeparators (src1), QDir::toNativeSeparators (src2)); 2184 if (result == QIMessageBox::Yes) 2185 { 2186 QString source = QString ("http://download.virtualbox.org/virtualbox/%1/") 2187 .arg (vbox.GetVersion().remove ("_OSE")) + name; 2188 QString target = QDir (vboxGlobal().virtualBox().GetHomeFolder()) 2189 .absoluteFilePath (name); 2190 2191 VBoxAdditionsDownloader *dl = 2192 new VBoxAdditionsDownloader (source, target, mDevicesInstallGuestToolsAction); 2193 statusBar()->addWidget (dl, 0); 2194 dl->start(); 2195 } 2196 } 2197 2198 void VBoxConsoleWnd::prepareStorageMenu() 2199 { 2200 QMenu *menu = qobject_cast <QMenu*> (sender()); 2201 Assert (menu); 2202 menu->clear(); 2203 2204 KDeviceType deviceType = menu == mDevicesCDMenu ? KDeviceType_DVD : 2205 menu == mDevicesFDMenu ? KDeviceType_Floppy : 2206 KDeviceType_Null; 2207 Assert (deviceType != KDeviceType_Null); 2208 2209 VBoxDefs::MediumType mediumType = menu == mDevicesCDMenu ? VBoxDefs::MediumType_DVD : 2210 menu == mDevicesFDMenu ? VBoxDefs::MediumType_Floppy : 2211 VBoxDefs::MediumType_Invalid; 2212 Assert (mediumType != VBoxDefs::MediumType_Invalid); 2213 2214 CMachine machine = mSession.GetMachine(); 2215 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 2216 foreach (const CMediumAttachment &attachment, attachments) 2217 { 2218 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 2219 if ( !controller.isNull() 2220 && (attachment.GetType() == deviceType)) 2221 { 2222 /* Attachment menu item */ 2223 QMenu *attachmentMenu = 0; 2224 if (menu->menuAction()->data().toInt() > 1) 2225 { 2226 attachmentMenu = new QMenu (menu); 2227 attachmentMenu->setTitle (QString ("%1 (%2)").arg (controller.GetName()) 2228 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), 2229 attachment.GetPort(), 2230 attachment.GetDevice())))); 2231 switch (controller.GetBus()) 2232 { 2233 case KStorageBus_IDE: 2234 attachmentMenu->setIcon (QIcon (":/ide_16px.png")); break; 2235 case KStorageBus_SATA: 2236 attachmentMenu->setIcon (QIcon (":/sata_16px.png")); break; 2237 case KStorageBus_SCSI: 2238 attachmentMenu->setIcon (QIcon (":/scsi_16px.png")); break; 2239 case KStorageBus_Floppy: 2240 attachmentMenu->setIcon (QIcon (":/floppy_16px.png")); break; 2241 default: 2242 break; 2243 } 2244 menu->addMenu (attachmentMenu); 2245 } 2246 else attachmentMenu = menu; 2247 2248 /* Mount Medium actions */ 2249 CMediumVector mediums; 2250 switch (mediumType) 2251 { 2252 case VBoxDefs::MediumType_DVD: 2253 mediums += vboxGlobal().virtualBox().GetHost().GetDVDDrives(); 2254 mediums += vboxGlobal().virtualBox().GetDVDImages(); 2255 break; 2256 case VBoxDefs::MediumType_Floppy: 2257 mediums += vboxGlobal().virtualBox().GetHost().GetFloppyDrives(); 2258 mediums += vboxGlobal().virtualBox().GetFloppyImages(); 2259 break; 2260 default: 2261 break; 2262 } 2263 2264 int mediumsToBeShown = 0; 2265 const int maxMediumsToBeShown = 5; 2266 CMedium currentMedium = attachment.GetMedium(); 2267 QString currentId = currentMedium.isNull() ? QString::null : currentMedium.GetId(); 2268 bool currentUsed = false; 2269 foreach (CMedium medium, mediums) 2270 { 2271 bool isMediumUsed = false; 2272 foreach (const CMediumAttachment &otherAttachment, attachments) 2273 { 2274 if (otherAttachment != attachment) 2275 { 2276 CMedium otherMedium = otherAttachment.GetMedium(); 2277 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 2278 { 2279 isMediumUsed = true; 2280 break; 2281 } 2282 } 2283 } 2284 if (!isMediumUsed) 2285 { 2286 if (!currentUsed && !currentMedium.isNull() && mediumsToBeShown == maxMediumsToBeShown - 1) 2287 medium = currentMedium; 2288 2289 if (medium.GetId() == currentId) 2290 currentUsed = true; 2291 2292 QAction *mountMediumAction = new QAction (VBoxMedium (medium, mediumType).name(), attachmentMenu); 2293 mountMediumAction->setCheckable (true); 2294 mountMediumAction->setChecked (!currentMedium.isNull() && medium.GetId() == currentId); 2295 mountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2296 attachment.GetPort(), 2297 attachment.GetDevice(), 2298 medium.GetId()))); 2299 connect (mountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2300 attachmentMenu->addAction (mountMediumAction); 2301 ++ mediumsToBeShown; 2302 if (mediumsToBeShown == maxMediumsToBeShown) 2303 break; 2304 } 2305 } 2306 2307 /* Virtual Media Manager action */ 2308 QAction *callVMMAction = new QAction (attachmentMenu); 2309 callVMMAction->setIcon (QIcon (":/diskimage_16px.png")); 2310 callVMMAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2311 attachment.GetPort(), 2312 attachment.GetDevice(), 2313 mediumType))); 2314 connect (callVMMAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2315 attachmentMenu->addAction (callVMMAction); 2316 2317 /* Separator */ 2318 attachmentMenu->addSeparator(); 2319 2320 /* Unmount Medium action */ 2321 QAction *unmountMediumAction = new QAction (attachmentMenu); 2322 unmountMediumAction->setEnabled (!currentMedium.isNull()); 2323 unmountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2324 attachment.GetPort(), 2325 attachment.GetDevice()))); 2326 connect (unmountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2327 attachmentMenu->addAction (unmountMediumAction); 2328 2329 /* Switch CD/FD naming */ 2330 switch (mediumType) 2331 { 2332 case VBoxDefs::MediumType_DVD: 2333 callVMMAction->setText (tr ("More CD/DVD Images...")); 2334 unmountMediumAction->setText (tr ("Unmount CD/DVD Device")); 2335 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/cd_unmount_16px.png", 2336 ":/cd_unmount_dis_16px.png")); 2337 break; 2338 case VBoxDefs::MediumType_Floppy: 2339 callVMMAction->setText (tr ("More Floppy Images...")); 2340 unmountMediumAction->setText (tr ("Unmount Floppy Device")); 2341 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/fd_unmount_16px.png", 2342 ":/fd_unmount_dis_16px.png")); 2343 break; 2344 default: 2345 break; 2346 } 2347 } 2348 } 2349 2350 if (menu->menuAction()->data().toInt() == 0) 2351 { 2352 /* Empty menu item */ 2353 Assert (menu->isEmpty()); 2354 QAction *emptyMenuAction = new QAction (menu); 2355 emptyMenuAction->setEnabled (false); 2356 switch (mediumType) 2357 { 2358 case VBoxDefs::MediumType_DVD: 2359 emptyMenuAction->setText (tr ("No CD/DVD Devices Attached")); 2360 break; 2361 case VBoxDefs::MediumType_Floppy: 2362 emptyMenuAction->setText (tr ("No Floppy Devices Attached")); 2363 break; 2364 default: 2365 break; 2366 } 2367 emptyMenuAction->setIcon (VBoxGlobal::iconSet (":/delete_16px.png", ":/delete_dis_16px.png")); 2368 menu->addAction (emptyMenuAction); 2369 } 2370 } 2371 2372 void VBoxConsoleWnd::prepareNetworkMenu() 2373 { 2374 mDevicesNetworkMenu->clear(); 2375 mDevicesNetworkMenu->addAction (mDevicesNetworkDialogAction); 2376 } 2377 2378 void VBoxConsoleWnd::prepareSFMenu() 2379 { 2380 mDevicesSFMenu->clear(); 2381 mDevicesSFMenu->addAction (mDevicesSFDialogAction); 2382 } 2383 2384 void VBoxConsoleWnd::mountMedium() 2385 { 2386 /* Get sender action */ 2387 QAction *action = qobject_cast <QAction*> (sender()); 2388 Assert (action); 2389 2390 /* Get current machine */ 2391 CMachine machine = mSession.GetMachine(); 2392 2393 /* Get mount-target */ 2394 MountTarget target = action->data().value <MountTarget>(); 2395 2396 /* Current mount-target attributes */ 2397 CMediumAttachment currentAttachment = machine.GetMediumAttachment (target.name, target.port, target.device); 2398 CMedium currentMedium = currentAttachment.GetMedium(); 2399 QString currentId = currentMedium.isNull() ? QString ("") : currentMedium.GetId(); 2400 2401 /* New mount-target attributes */ 2402 QString newId = QString (""); 2403 bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid; 2404 2405 /* Open Virtual Media Manager to select image id */ 2406 if (selectWithMediaManager) 2407 { 2408 /* Search for already used images */ 2409 QStringList usedImages; 2410 foreach (const CMediumAttachment &attachment, machine.GetMediumAttachments()) 2411 { 2412 CMedium medium = attachment.GetMedium(); 2413 if (attachment != currentAttachment && !medium.isNull() && !medium.GetHostDrive()) 2414 usedImages << medium.GetId(); 2415 } 2416 /* Open VMM Dialog */ 2417 VBoxMediaManagerDlg dlg (this); 2418 dlg.setup (target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages); 2419 if (dlg.exec() == QDialog::Accepted) 2420 newId = dlg.selectedId(); 2421 else return; 2422 } 2423 /* Use medium which was sent */ 2424 else if (!target.id.isNull() && target.id != currentId) 2425 newId = target.id; 2426 2427 bool mount = !newId.isEmpty(); 2428 2429 /* Remount medium to the predefined port/device */ 2430 bool wasMounted = false; 2431 machine.MountMedium (target.name, target.port, target.device, newId, false /* force */); 2432 if (machine.isOk()) 2433 wasMounted = true; 2434 else 2435 { 2436 /* Ask for force remounting */ 2437 if (vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok) 2438 { 2439 /* Force remount medium to the predefined port/device. */ 2440 machine.MountMedium (target.name, target.port, target.device, newId, true /* force */); 2441 if (machine.isOk()) 2442 wasMounted = true; 2443 else 2444 vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */); 2445 } 2446 } 2447 2448 /* Save medium mounted at runtime */ 2449 if (wasMounted && mIsAutoSaveMedia) 2450 { 2451 machine.SaveSettings(); 2452 if (!machine.isOk()) 2453 vboxProblem().cannotSaveMachineSettings (machine); 2454 } 2455 } 2456 2457 /** 2458 * Attach/Detach selected USB Device. 2459 */ 2460 void VBoxConsoleWnd::switchUSB (QAction *aAction) 2461 { 2462 if (!mConsole) return; 2463 2464 CConsole console = mSession.GetConsole(); 2465 AssertWrapperOk (mSession); 2466 2467 CUSBDevice usb = mDevicesUSBMenu->getUSB (aAction); 2468 /* if null then some other item but a USB device is selected */ 2469 if (usb.isNull()) 2470 return; 2471 2472 if (!aAction->isChecked()) 2473 { 2474 console.DetachUSBDevice (usb.GetId()); 2475 if (!console.isOk()) 2476 { 2477 /// @todo (r=dmik) the dialog should be either modeless 2478 // or we have to pause the VM 2479 vboxProblem().cannotDetachUSBDevice (console, vboxGlobal().details (usb)); 2480 } 2481 } 2482 else 2483 { 2484 console.AttachUSBDevice (usb.GetId()); 2485 if (!console.isOk()) 2486 { 2487 /// @todo (r=dmik) the dialog should be either modeless 2488 // or we have to pause the VM 2489 vboxProblem().cannotAttachUSBDevice (console, vboxGlobal().details (usb)); 2490 } 2491 } 2492 } 2493 2494 void VBoxConsoleWnd::showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent) 2495 { 2496 if (aInd == mCDLed) 2497 { 2498 mDevicesCDMenu->exec (aEvent->globalPos()); 2499 } 2500 #if 0 /* TODO: Allow to setup status-bar! */ 2501 else if (aInd == mFDLed) 2502 { 2503 mDevicesFDMenu->exec (aEvent->globalPos()); 2504 } 2505 #endif 2506 else if (aInd == mNetLed) 2507 { 2508 if (mDevicesNetworkMenu->isEnabled()) 2509 mDevicesNetworkMenu->exec (aEvent->globalPos()); 2510 } 2511 else if (aInd == mUSBLed) 2512 { 2513 if (mDevicesUSBMenu->isEnabled()) 2514 mDevicesUSBMenu->exec (aEvent->globalPos()); 2515 } 2516 else if (aInd == mSFLed) 2517 { 2518 if (mDevicesSFMenu->isEnabled()) 2519 mDevicesSFMenu->exec (aEvent->globalPos()); 2520 } 2521 else if (aInd == mMouseLed) 2522 { 2523 mVmDisMouseIntegrMenu->exec (aEvent->globalPos()); 2524 } 2525 #if 0 /* TODO: Allow to setup status-bar! */ 2526 else if (aInd == mVrdpLed) 2527 { 2528 mDevicesVRDPMenu->exec (aEvent->globalPos()); 2529 } 2530 else if (aInd == mAutoresizeLed) 2531 { 2532 mVmAutoresizeMenu->exec (aEvent->globalPos()); 2533 } 2534 #endif 2535 } 2536 2537 void VBoxConsoleWnd::updateDeviceLights() 2538 { 2539 if (mConsole) 2540 { 2541 CConsole &console = mConsole->console(); 2542 int st; 2543 if (mHDLed->state() != KDeviceActivity_Null) 2544 { 2545 st = console.GetDeviceActivity (KDeviceType_HardDisk); 2546 if (mHDLed->state() != st) 2547 mHDLed->setState (st); 2548 } 2549 if (mCDLed->state() != KDeviceActivity_Null) 2550 { 2551 st = console.GetDeviceActivity (KDeviceType_DVD); 2552 if (mCDLed->state() != st) 2553 mCDLed->setState (st); 2554 } 2555 #if 0 /* TODO: Allow to setup status-bar! */ 2556 if (mFDLed->state() != KDeviceActivity_Null) 2557 { 2558 st = console.GetDeviceActivity (KDeviceType_Floppy); 2559 if (mFDLed->state() != st) 2560 mFDLed->setState (st); 2561 } 2562 #endif 2563 if (mNetLed->state() != KDeviceActivity_Null) 2564 { 2565 st = console.GetDeviceActivity (KDeviceType_Network); 2566 if (mNetLed->state() != st) 2567 mNetLed->setState (st); 2568 } 2569 if (mUSBLed->state() != KDeviceActivity_Null) 2570 { 2571 st = console.GetDeviceActivity (KDeviceType_USB); 2572 if (mUSBLed->state() != st) 2573 mUSBLed->setState (st); 2574 } 2575 if (mSFLed->state() != KDeviceActivity_Null) 2576 { 2577 st = console.GetDeviceActivity (KDeviceType_SharedFolder); 2578 if (mSFLed->state() != st) 2579 mSFLed->setState (st); 2580 } 2581 } 2582 } 2583 2584 void VBoxConsoleWnd::updateMachineState (KMachineState aState) 2585 { 2586 bool guruMeditation = false; 2587 2588 if (mConsole && mMachineState != aState) 2589 { 2590 switch (aState) 2591 { 2592 case KMachineState_Stuck: 2593 { 2594 guruMeditation = true; 2595 break; 2596 } 2597 case KMachineState_Paused: 2598 { 2599 if (!mVmPauseAction->isChecked()) 2600 mVmPauseAction->setChecked (true); 2601 break; 2602 } 2603 case KMachineState_Running: 2604 case KMachineState_Teleporting: /** @todo Live Migration: Check out this. */ 2605 case KMachineState_LiveSnapshotting: 2606 { 2607 if ( ( mMachineState == KMachineState_Paused 2608 || mMachineState == KMachineState_TeleportingPausedVM) 2609 && mVmPauseAction->isChecked() 2610 ) 2611 mVmPauseAction->setChecked (false); 2612 break; 2613 } 2614 #ifdef Q_WS_X11 2615 case KMachineState_Starting: 2616 case KMachineState_Restoring: 2617 case KMachineState_TeleportingIn: 2618 { 2619 /* The keyboard handler may wish to do some release logging 2620 on startup. Tell it that the logger is now active. */ 2621 doXKeyboardLogging (QX11Info::display()); 2622 break; 2623 } 2624 #endif 2625 default: 2626 break; 2627 } 2628 2629 bool isRunningOrPaused = aState == KMachineState_Running 2630 || aState == KMachineState_Teleporting 2631 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2632 || aState == KMachineState_Paused; 2633 2634 /* Enable/Disable actions that are not managed by updateAppearanceOf() */ 2635 2636 mRunningActions->setEnabled ( aState == KMachineState_Running 2637 || aState == KMachineState_Teleporting 2638 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2639 ); 2640 mRunningOrPausedActions->setEnabled (isRunningOrPaused); 2641 2642 mMachineState = aState; 2643 2644 updateAppearanceOf (Caption | 2645 HardDiskStuff | DVDStuff | FloppyStuff | 2646 NetworkStuff | USBStuff | VRDPStuff | 2647 PauseAction | DisableMouseIntegrAction); 2648 2649 if ( aState == KMachineState_PoweredOff 2650 || aState == KMachineState_Saved 2651 || aState == KMachineState_Teleported 2652 || aState == KMachineState_Aborted 2653 ) 2654 { 2655 /* VM has been powered off or saved or aborted, no matter 2656 * internally or externally -- we must *safely* close the console 2657 * window unless auto closure is disabled. */ 2658 if (!mNoAutoClose) 2659 tryClose(); 2660 } 2661 } 2662 2663 if (guruMeditation) 2664 { 2665 mConsole->setIgnoreGuestResize (true); 2666 2667 CConsole console = mConsole->console(); 2668 QString logFolder = console.GetMachine().GetLogFolder(); 2669 2670 /* Take the screenshot for debugging purposes and save it */ 2671 QString fname = logFolder + "/VBox.png"; 2672 2673 CDisplay dsp = console.GetDisplay(); 2674 QImage shot = QImage (dsp.GetWidth(), dsp.GetHeight(), QImage::Format_RGB32); 2675 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 2676 shot.save (QFile::encodeName (fname), "PNG"); 2677 2678 if (vboxProblem().remindAboutGuruMeditation (console, QDir::toNativeSeparators (logFolder))) 2679 { 2680 qApp->processEvents(); 2681 console.PowerDown(); 2682 if (!console.isOk()) 2683 vboxProblem().cannotStopMachine (console); 2684 } 2685 } 2686 2687 #ifdef Q_WS_MAC 2688 if (mConsole) 2689 mConsole->updateDockOverlay(); 2690 #endif 2691 } 2692 2693 void VBoxConsoleWnd::updateMouseState (int aState) 2694 { 2695 mVmDisableMouseIntegrAction->setEnabled (aState & VBoxConsoleView::MouseAbsolute); 2696 2697 if ((aState & VBoxConsoleView::MouseAbsoluteDisabled) && 2698 (aState & VBoxConsoleView::MouseAbsolute) && 2699 !(aState & VBoxConsoleView::MouseCaptured)) 2700 { 2701 mMouseLed->setState (4); 2702 } 2703 else 2704 { 2705 mMouseLed->setState (aState & (VBoxConsoleView::MouseAbsolute | VBoxConsoleView::MouseCaptured)); 2706 } 2707 } 2708 2709 void VBoxConsoleWnd::updateAdditionsState (const QString &aVersion, 2710 bool aActive, 2711 bool aSeamlessSupported, 2712 bool aGraphicsSupported) 2713 { 2714 mVmAutoresizeGuestAction->setEnabled (aActive && aGraphicsSupported); 2715 if ((mIsSeamlessSupported != aSeamlessSupported) || 2716 (mIsGraphicsSupported != aGraphicsSupported)) 2717 { 2718 mVmSeamlessAction->setEnabled (aSeamlessSupported && aGraphicsSupported); 2719 mIsSeamlessSupported = aSeamlessSupported; 2720 mIsGraphicsSupported = aGraphicsSupported; 2721 /* If seamless mode should be enabled then check if it is enabled 2722 * currently and re-enable it if open-view procedure is finished */ 2723 if (mVmSeamlessAction->isChecked() && mIsOpenViewFinished && aSeamlessSupported && aGraphicsSupported) 2724 toggleFullscreenMode (true, true); 2725 /* Disable auto-resizing if advanced graphics are not available */ 2726 mConsole->setAutoresizeGuest (mIsGraphicsSupported && mVmAutoresizeGuestAction->isChecked()); 2727 mVmAutoresizeGuestAction->setEnabled (mIsGraphicsSupported); 2728 } 2729 2730 /* Check the GA version only in case of additions are active */ 2731 if (!aActive) 2732 return; 2733 2734 /* Check the Guest Additions version and warn the user about possible 2735 * compatibility issues in case if the installed version is outdated. */ 2736 uint version = aVersion.toUInt(); 2737 QString versionStr = QString ("%1.%2") 2738 .arg (RT_HIWORD (version)).arg (RT_LOWORD (version)); 2739 QString expectedStr = QString ("%1.%2") 2740 .arg (VMMDEV_VERSION_MAJOR).arg (VMMDEV_VERSION_MINOR); /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 2741 2742 if (RT_HIWORD (version) < VMMDEV_VERSION_MAJOR) 2743 { 2744 vboxProblem().warnAboutTooOldAdditions (this, versionStr, expectedStr); 2745 } 2746 else if (RT_HIWORD (version) == VMMDEV_VERSION_MAJOR && 2747 RT_LOWORD (version) < VMMDEV_VERSION_MINOR) 2748 { 2749 vboxProblem().warnAboutOldAdditions (this, versionStr, expectedStr); 2750 } 2751 else if (version > VMMDEV_VERSION) 2752 { 2753 vboxProblem().warnAboutNewAdditions (this, versionStr, expectedStr); 2754 } 2755 } 2756 2757 void VBoxConsoleWnd::updateNetworkAdaptersState() 2758 { 2759 updateAppearanceOf (NetworkStuff); 2760 } 2761 2762 void VBoxConsoleWnd::updateUsbState() 2763 { 2764 updateAppearanceOf (USBStuff); 2765 } 2766 2767 void VBoxConsoleWnd::updateMediaDriveState (VBoxDefs::MediumType aType) 2768 { 2769 Assert (aType == VBoxDefs::MediumType_DVD || aType == VBoxDefs::MediumType_Floppy); 2770 updateAppearanceOf (aType == VBoxDefs::MediumType_DVD ? DVDStuff : 2771 aType == VBoxDefs::MediumType_Floppy ? FloppyStuff : 2772 AllStuff); 2773 } 2774 2775 void VBoxConsoleWnd::updateSharedFoldersState() 2776 { 2777 updateAppearanceOf (SharedFolderStuff); 2778 } 2779 2780 /** 2781 * This slot is called just after leaving the fullscreen/seamless mode, 2782 * when the console was resized to previous size. 2783 */ 2784 void VBoxConsoleWnd::onExitFullscreen() 2785 { 2786 mConsole->setIgnoreMainwndResize (false); 2787 } 2788 2789 void VBoxConsoleWnd::unlockActionsSwitch() 2790 { 2791 if (mIsSeamless) 2792 mVmSeamlessAction->setEnabled (true); 2793 else if (mIsFullscreen) 2794 mVmFullscreenAction->setEnabled (true); 2795 else 2796 { 2797 mVmSeamlessAction->setEnabled (mIsSeamlessSupported && mIsGraphicsSupported); 2798 mVmFullscreenAction->setEnabled (true); 2799 } 2800 2801 #ifdef Q_WS_MAC 2802 if (!mIsSeamless) 2803 { 2804 /* Fade back to the normal gamma */ 2805 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 2806 CGReleaseDisplayFadeReservation (mFadeToken); 2807 } 2808 mConsole->setMouseCoalescingEnabled (true); 2809 #endif 2810 2811 #ifdef Q_WS_X11 2812 if (vboxGlobal().isKWinManaged() && !mIsSeamless && !mIsFullscreen) 2813 { 2814 /* Workaround for a KWin bug to let console window to exit 2815 * seamless mode correctly. */ 2816 setWindowFlags(Qt::Window); 2817 setVisible(true); 2818 } 2819 #endif 2820 } 2821 2822 void VBoxConsoleWnd::mtExitMode() 2823 { 2824 if (mIsSeamless) 2825 mVmSeamlessAction->toggle(); 2826 else 2827 mVmFullscreenAction->toggle(); 2828 } 2829 2830 void VBoxConsoleWnd::mtCloseVM() 2831 { 2832 mVmCloseAction->trigger(); 2833 } 2834 2835 void VBoxConsoleWnd::mtMaskUpdate() 2836 { 2837 if (mIsSeamless) 2838 setMask (mConsole->lastVisibleRegion()); 2839 } 2840 2841 void VBoxConsoleWnd::changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent) 2842 { 2843 #ifdef Q_WS_MAC 2844 if (mConsole) 2845 { 2846 mConsole->setDockIconEnabled (aEvent.mChanged); 2847 mConsole->updateDockOverlay(); 2848 } 2849 #else 2850 Q_UNUSED (aEvent); 2851 #endif 2852 } 2853 2854 void VBoxConsoleWnd::changePresentationMode (const VBoxChangePresentationModeEvent &aEvent) 2855 { 2856 Q_UNUSED (aEvent); 2857 #ifdef Q_WS_MAC 2858 # ifdef QT_MAC_USE_COCOA 2859 if (mIsFullscreen) 2860 { 2861 /* First check if we are on the primary screen, only than the 2862 presentation mode have to be changed. */ 2863 QDesktopWidget* pDesktop = QApplication::desktop(); 2864 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 2865 { 2866 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_PresentationModeEnabled).toLower(); 2867 /* Default to false if it is an empty value */ 2868 if (testStr.isEmpty() || testStr == "false") 2869 SetSystemUIMode (kUIModeAllHidden, 0); 2870 else 2871 SetSystemUIMode (kUIModeAllSuppressed, 0); 2872 } 2873 } 2874 else 2875 SetSystemUIMode (kUIModeNormal, 0); 2876 # endif /* QT_MAC_USE_COCOA */ 2877 #endif 2878 } 2879 2880 /** 2881 * Called (on non-UI thread!) when a global GUI setting changes. 2882 */ 2883 void VBoxConsoleWnd::processGlobalSettingChange (const char * /* aPublicName */, const char * /* aName */) 2884 { 2885 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 2886 } 2887 2888 /** 2889 * This function checks the status of required features and 2890 * makes a warning and/or some action if something necessary 2891 * is not in good condition. 2892 * Does nothing if no console view was opened. 2893 */ 2894 void VBoxConsoleWnd::checkRequiredFeatures() 2895 { 2896 if (!mConsole) return; 2897 2898 CConsole console = mConsole->console(); 2899 2900 /* Check if the virtualization feature is required. */ 2901 bool is64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType ( 2902 console.GetGuest().GetOSTypeId()).GetIs64Bit(); 2903 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType ( 2904 console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 2905 Assert(!is64BitsGuest || fRecommendVirtEx); 2906 bool isVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 2907 if (fRecommendVirtEx && !isVirtEnabled) 2908 { 2909 bool ret; 2910 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost() 2911 .GetProcessorFeature (KProcessorFeature_HWVirtEx); 2912 2913 vmPause (true); 2914 2915 if (is64BitsGuest) 2916 ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported); 2917 else 2918 ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported); 2919 2920 if (ret == true) 2921 close(); 2922 else 2923 vmPause (false); 2924 } 2925 } 2926 2927 void VBoxConsoleWnd::activateUICustomizations() 2928 { 2929 VBoxGlobalSettings settings = vboxGlobal().settings(); 2930 /* Process known keys */ 2931 menuBar()->setHidden (settings.isFeatureActive ("noMenuBar")); 2932 statusBar()->setHidden (settings.isFeatureActive ("noStatusBar")); 2933 } 2934 2935 void VBoxConsoleWnd::updateAppearanceOf (int aElement) 2936 { 2937 if (!mConsole) return; 2938 2939 CMachine machine = mSession.GetMachine(); 2940 CConsole console = mConsole->console(); 2941 2942 bool isStrictRunningOrPaused = mMachineState == KMachineState_Running 2943 || mMachineState == KMachineState_Paused; 2944 bool isRunningOrPaused = isStrictRunningOrPaused 2945 || mMachineState == KMachineState_Teleporting 2946 || mMachineState == KMachineState_LiveSnapshotting; 2947 2948 if (aElement & Caption) 2949 { 2950 QString snapshotName; 2951 if (machine.GetSnapshotCount() > 0) 2952 { 2953 CSnapshot snapshot = machine.GetCurrentSnapshot(); 2954 snapshotName = " (" + snapshot.GetName() + ")"; 2955 } 2956 setWindowTitle (machine.GetName() + snapshotName + 2957 " [" + vboxGlobal().toString (mMachineState) + "] - " + 2958 mCaptionPrefix); 2959 mMiniToolBar->setDisplayText (machine.GetName() + snapshotName); 2960 } 2961 if (aElement & HardDiskStuff) 2962 { 2963 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2964 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 2965 QString data; 2966 bool attachmentsPresent = false; 2967 2968 CStorageControllerVector controllers = machine.GetStorageControllers(); 2969 foreach (const CStorageController &controller, controllers) 2970 { 2971 QString attData; 2972 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 2973 foreach (const CMediumAttachment &attachment, attachments) 2974 { 2975 if (attachment.GetType() != KDeviceType_HardDisk) 2976 continue; 2977 attData += QString ("<br> <nobr>%1: %2</nobr>") 2978 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 2979 .arg (VBoxMedium (attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 2980 attachmentsPresent = true; 2981 } 2982 if (!attData.isNull()) 2983 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 2984 } 2985 2986 if (!attachmentsPresent) 2987 data += tr ("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 2988 2989 mHDLed->setToolTip (tip.arg (data)); 2990 mHDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 2991 } 2992 if (aElement & DVDStuff) 2993 { 2994 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2995 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 2996 QString data; 2997 bool attachmentsPresent = false; 2998 2999 CStorageControllerVector controllers = machine.GetStorageControllers(); 3000 foreach (const CStorageController &controller, controllers) 3001 { 3002 QString attData; 3003 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3004 foreach (const CMediumAttachment &attachment, attachments) 3005 { 3006 if (attachment.GetType() != KDeviceType_DVD) 3007 continue; 3008 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_DVD); 3009 attData += QString ("<br> <nobr>%1: %2</nobr>") 3010 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3011 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3012 if (!vboxMedium.isNull()) 3013 attachmentsPresent = true; 3014 } 3015 if (!attData.isNull()) 3016 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3017 } 3018 3019 if (data.isNull()) 3020 data = tr ("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 3021 3022 mCDLed->setToolTip (tip.arg (data)); 3023 mCDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3024 } 3025 #if 0 /* TODO: Allow to setup status-bar! */ 3026 if (aElement & FloppyStuff) 3027 { 3028 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 3029 "of the floppy devices:</nobr>%1</p>", "FD tooltip"); 3030 QString data; 3031 bool attachmentsPresent = false; 3032 3033 CStorageControllerVector controllers = machine.GetStorageControllers(); 3034 foreach (const CStorageController &controller, controllers) 3035 { 3036 QString attData; 3037 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3038 foreach (const CMediumAttachment &attachment, attachments) 3039 { 3040 if (attachment.GetType() != KDeviceType_Floppy) 3041 continue; 3042 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_Floppy); 3043 attData += QString ("<br> <nobr>%1: %2</nobr>") 3044 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3045 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3046 if (!vboxMedium.isNull()) 3047 attachmentsPresent = true; 3048 } 3049 if (!attData.isNull()) 3050 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3051 } 3052 3053 if (data.isNull()) 3054 data = tr ("<br><nobr><b>No floppy devices attached</b></nobr>", "FD tooltip"); 3055 3056 mFDLed->setToolTip (tip.arg (data)); 3057 mFDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3058 } 3059 #endif 3060 if (aElement & NetworkStuff) 3061 { 3062 ulong maxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 3063 ulong count = 0; 3064 for (ulong slot = 0; slot < maxCount; ++ slot) 3065 if (machine.GetNetworkAdapter (slot).GetEnabled()) 3066 ++ count; 3067 mNetLed->setState (count > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 3068 3069 mDevicesNetworkDialogAction->setEnabled (isStrictRunningOrPaused && count > 0); 3070 mDevicesNetworkMenu->setEnabled (isStrictRunningOrPaused && count > 0); 3071 3072 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of the " 3073 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 3074 QString info; 3075 3076 for (ulong slot = 0; slot < maxCount; ++ slot) 3077 { 3078 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot); 3079 if (adapter.GetEnabled()) 3080 info += tr ("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 3081 .arg (slot + 1) 3082 .arg (vboxGlobal().toString (adapter.GetAttachmentType())) 3083 .arg (adapter.GetCableConnected() ? 3084 tr ("connected", "Network adapters tooltip") : 3085 tr ("disconnected", "Network adapters tooltip")); 3086 } 3087 3088 if (info.isNull()) 3089 info = tr ("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 3090 3091 mNetLed->setToolTip (tip.arg (info)); 3092 } 3093 if (aElement & USBStuff) 3094 { 3095 if (!mUSBLed->isHidden()) 3096 { 3097 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3098 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 3099 QString info; 3100 3101 CUSBController usbctl = machine.GetUSBController(); 3102 if (!usbctl.isNull() && usbctl.GetEnabled()) 3103 { 3104 mDevicesUSBMenu->setEnabled (isStrictRunningOrPaused); 3105 3106 CUSBDeviceVector devsvec = console.GetUSBDevices(); 3107 for (int i = 0; i < devsvec.size(); ++ i) 3108 { 3109 CUSBDevice usb = devsvec [i]; 3110 info += QString ("<br><b><nobr>%1</nobr></b>").arg (vboxGlobal().details (usb)); 3111 } 3112 if (info.isNull()) 3113 info = tr ("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 3114 } 3115 else 3116 { 3117 mDevicesUSBMenu->setEnabled (false); 3118 info = tr ("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 3119 } 3120 3121 mUSBLed->setToolTip (tip.arg (info)); 3122 } 3123 } 3124 if (aElement & VRDPStuff) 3125 { 3126 CVRDPServer vrdpsrv = mSession.GetMachine().GetVRDPServer(); 3127 if (!vrdpsrv.isNull()) 3128 { 3129 /* update menu&status icon state */ 3130 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 3131 mDevicesSwitchVrdpAction->setChecked (isVRDPEnabled); 3132 #if 0 /* TODO: Allow to setup status-bar! */ 3133 mVrdpLed->setState (isVRDPEnabled ? 1 : 0); 3134 3135 QString tip = tr ("Indicates whether the Remote Display (VRDP Server) " 3136 "is enabled (<img src=:/vrdp_16px.png/>) or not " 3137 "(<img src=:/vrdp_disabled_16px.png/>)."); 3138 if (vrdpsrv.GetEnabled()) 3139 tip += tr ("<hr>The VRDP Server is listening on port %1").arg (vrdpsrv.GetPort()); 3140 mVrdpLed->setToolTip (tip); 3141 #endif 3142 } 3143 } 3144 if (aElement & SharedFolderStuff) 3145 { 3146 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3147 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 3148 3149 QString data; 3150 QMap <QString, QString> sfs; 3151 3152 mDevicesSFMenu->setEnabled (true); 3153 3154 /* Permanent folders */ 3155 CSharedFolderVector psfvec = machine.GetSharedFolders(); 3156 3157 for (int i = 0; i < psfvec.size(); ++ i) 3158 { 3159 CSharedFolder sf = psfvec [i]; 3160 sfs.insert (sf.GetName(), sf.GetHostPath()); 3161 } 3162 3163 /* Transient folders */ 3164 CSharedFolderVector tsfvec = console.GetSharedFolders(); 3165 3166 for (int i = 0; i < tsfvec.size(); ++ i) 3167 { 3168 CSharedFolder sf = tsfvec[i]; 3169 sfs.insert (sf.GetName(), sf.GetHostPath()); 3170 } 3171 3172 for (QMap <QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 3173 { 3174 /* Select slashes depending on the OS type */ 3175 if (VBoxGlobal::isDOSType (console.GetGuest().GetOSTypeId())) 3176 data += QString ("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 3177 .arg (it.key(), it.value()); 3178 else 3179 data += QString ("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 3180 .arg (it.key(), it.value()); 3181 } 3182 3183 if (sfs.count() == 0) 3184 data = tr ("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 3185 3186 mSFLed->setToolTip (tip.arg (data)); 3187 } 3188 if (aElement & VirtualizationStuff) 3189 { 3190 bool virtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 3191 QString virtualization = virtEnabled ? 3192 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") : 3193 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)"); 3194 3195 bool nestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 3196 QString nestedPaging = nestEnabled ? 3197 VBoxVMInformationDlg::tr ("Enabled", "nested paging") : 3198 VBoxVMInformationDlg::tr ("Disabled", "nested paging"); 3199 3200 QString tip (tr ("Indicates the status of the hardware virtualization " 3201 "features used by this virtual machine:" 3202 "<br><nobr><b>%1:</b> %2</nobr>" 3203 "<br><nobr><b>%3:</b> %4</nobr>", 3204 "Virtualization Stuff LED") 3205 .arg (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization) 3206 .arg (VBoxVMInformationDlg::tr ("Nested Paging"), nestedPaging)); 3207 3208 int cpuCount = console.GetMachine().GetCPUCount(); 3209 if (cpuCount > 1) 3210 tip += tr ("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 3211 .arg (VBoxGlobal::tr ("Processor(s)", "details report")).arg (cpuCount); 3212 3213 mVirtLed->setToolTip (tip); 3214 mVirtLed->setState (virtEnabled); 3215 } 3216 if (aElement & PauseAction) 3217 { 3218 if (!mVmPauseAction->isChecked()) 3219 { 3220 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Pause"), "P")); 3221 mVmPauseAction->setStatusTip (tr ("Suspend the execution of the virtual machine")); 3222 } 3223 else 3224 { 3225 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("R&esume"), "P")); 3226 mVmPauseAction->setStatusTip (tr ("Resume the execution of the virtual machine" ) ); 3227 } 3228 mVmPauseAction->setEnabled (isRunningOrPaused); 3229 } 3230 if (aElement & DisableMouseIntegrAction) 3231 { 3232 if (!mVmDisableMouseIntegrAction->isChecked()) 3233 { 3234 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Disable &Mouse Integration"), "I")); 3235 mVmDisableMouseIntegrAction->setStatusTip (tr ("Temporarily disable host mouse pointer integration")); 3236 } 3237 else 3238 { 3239 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Enable &Mouse Integration"), "I")); 3240 mVmDisableMouseIntegrAction->setStatusTip (tr ("Enable temporarily disabled host mouse pointer integration")); 3241 } 3242 if ( mMachineState == KMachineState_Running 3243 || mMachineState == KMachineState_Teleporting 3244 || mMachineState == KMachineState_LiveSnapshotting 3245 ) 3246 mVmDisableMouseIntegrAction->setEnabled (mConsole->isMouseAbsolute()); 3247 else 3248 mVmDisableMouseIntegrAction->setEnabled (false); 3249 } 3250 } 3251 3252 /** 3253 * @return @c true if successfully performed the requested operation and false 3254 * otherwise. 3255 */ 3256 bool VBoxConsoleWnd::toggleFullscreenMode (bool aOn, bool aSeamless) 3257 { 3258 /* Please note: For some platforms like the Mac, the calling order of the 3259 * functions in this methods is vital. So please be careful on changing 3260 * this. */ 3261 3262 QSize initialSize = size(); 3263 if (aSeamless || mConsole->isAutoresizeGuestActive()) 3264 { 3265 QRect screen = aSeamless ? 3266 QApplication::desktop()->availableGeometry (this) : 3267 QApplication::desktop()->screenGeometry (this); 3268 ULONG64 availBits = mSession.GetMachine().GetVRAMSize() /* vram */ 3269 * _1M /* mb to bytes */ 3270 * 8; /* to bits */ 3271 ULONG guestBpp = mConsole->console().GetDisplay().GetBitsPerPixel(); 3272 ULONG64 usedBits = (screen.width() /* display width */ 3273 * screen.height() /* display height */ 3274 * guestBpp 3275 + _1M * 8) /* current cache per screen - may be changed in future */ 3276 * mSession.GetMachine().GetMonitorCount() /**< @todo fix assumption that all screens have same resolution */ 3277 + 4096 * 8; /* adapter info */ 3278 if (aOn && (availBits < usedBits)) 3279 { 3280 if (aSeamless) 3281 { 3282 vboxProblem().cannotEnterSeamlessMode ( 3283 screen.width(), screen.height(), guestBpp, 3284 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3285 return false; 3286 } 3287 else 3288 { 3289 int result = vboxProblem().cannotEnterFullscreenMode ( 3290 screen.width(), screen.height(), guestBpp, 3291 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3292 if (result == QIMessageBox::Cancel) 3293 return false; 3294 } 3295 } 3296 } 3297 3298 AssertReturn (mConsole, false); 3299 AssertReturn ((mHiddenChildren.empty() == aOn), false); 3300 AssertReturn ((aSeamless && mIsSeamless != aOn) || 3301 (!aSeamless && mIsFullscreen != aOn), false); 3302 if (aOn) 3303 AssertReturn ((aSeamless && !mIsFullscreen) || 3304 (!aSeamless && !mIsSeamless), false); 3305 3306 if (aOn) 3307 { 3308 /* Take the toggle hot key from the menu item. Since 3309 * VBoxGlobal::extractKeyFromActionText gets exactly the 3310 * linked key without the 'Host+' part we are adding it here. */ 3311 QString hotKey = QString ("Host+%1") 3312 .arg (VBoxGlobal::extractKeyFromActionText (aSeamless ? 3313 mVmSeamlessAction->text() : mVmFullscreenAction->text())); 3314 3315 Assert (!hotKey.isEmpty()); 3316 3317 /* Show the info message. */ 3318 bool ok = aSeamless ? 3319 vboxProblem().confirmGoingSeamless (hotKey) : 3320 vboxProblem().confirmGoingFullscreen (hotKey); 3321 if (!ok) 3322 return false; 3323 } 3324 3325 #ifdef Q_WS_MAC 3326 if (!aSeamless) 3327 { 3328 /* Fade to black */ 3329 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken); 3330 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); 3331 } 3332 #endif 3333 3334 if (aSeamless) 3335 { 3336 /* Activate the auto-resize feature required for the seamless mode. */ 3337 if (!mVmAutoresizeGuestAction->isChecked()) 3338 mVmAutoresizeGuestAction->setChecked (true); 3339 3340 /* Activate the mouse integration feature for the seamless mode. */ 3341 if (mVmDisableMouseIntegrAction->isChecked()) 3342 mVmDisableMouseIntegrAction->setChecked (false); 3343 3344 mVmAdjustWindowAction->setEnabled (!aOn); 3345 mVmFullscreenAction->setEnabled (!aOn); 3346 mVmAutoresizeGuestAction->setEnabled (!aOn); 3347 mVmDisableMouseIntegrAction->setEnabled (!aOn); 3348 3349 mConsole->console().GetDisplay().SetSeamlessMode (aOn); 3350 mIsSeamless = aOn; 3351 } 3352 else 3353 { 3354 mIsFullscreen = aOn; 3355 mVmAdjustWindowAction->setEnabled (!aOn); 3356 mVmSeamlessAction->setEnabled (!aOn && mIsSeamlessSupported && mIsGraphicsSupported); 3357 } 3358 3359 bool wasHidden = isHidden(); 3360 3361 /* Temporarily disable the mode-related action to make sure 3362 * user can not leave the mode before he enter it and inside out. */ 3363 aSeamless ? mVmSeamlessAction->setEnabled (false) : 3364 mVmFullscreenAction->setEnabled (false); 3365 3366 /* Calculate initial console size */ 3367 QSize consoleSize; 3368 3369 if (aOn) 3370 { 3371 consoleSize = mConsole->frameSize(); 3372 consoleSize -= QSize (mConsole->frameWidth() * 2, mConsole->frameWidth() * 2); 3373 3374 /* Toggle console to manual resize mode. */ 3375 mConsole->setIgnoreMainwndResize (true); 3376 3377 /* Memorize the maximized state. */ 3378 QDesktopWidget *dtw = QApplication::desktop(); 3379 mWasMax = isWindowMaximized() && 3380 dtw->availableGeometry().width() == frameSize().width() && 3381 dtw->availableGeometry().height() == frameSize().height(); 3382 3383 /* Save the previous scroll-view minimum size before entering 3384 * fullscreen/seamless state to restore this minimum size before 3385 * the exiting fullscreen. Required for correct scroll-view and 3386 * guest display update in SDL mode. */ 3387 mPrevMinSize = mConsole->minimumSize(); 3388 mConsole->setMinimumSize (0, 0); 3389 3390 /* let the widget take the whole available desktop space */ 3391 QRect scrGeo = aSeamless ? 3392 dtw->availableGeometry (this) : dtw->screenGeometry (this); 3393 3394 /* It isn't guaranteed that the guest os set the video mode that 3395 * we requested. So after all the resizing stuff set the clipping 3396 * mask and the spacing shifter to the corresponding values. */ 3397 if (aSeamless) 3398 setViewInSeamlessMode (scrGeo); 3399 3400 #ifdef Q_WS_WIN 3401 mPrevRegion = dtw->screenGeometry (this); 3402 #endif 3403 3404 /* Hide all but the central widget containing the console view. */ 3405 QList <QWidget*> list (findChildren <QWidget*> ()); 3406 QList <QWidget*> excludes; 3407 excludes << centralWidget() << centralWidget()->findChildren <QWidget*> (); 3408 foreach (QWidget *w, list) 3409 { 3410 if (!excludes.contains (w)) 3411 { 3412 if (!w->isHidden()) 3413 { 3414 w->hide(); 3415 mHiddenChildren.append (w); 3416 } 3417 } 3418 } 3419 3420 /* Adjust colors and appearance. */ 3421 mErasePalette = centralWidget()->palette(); 3422 QPalette palette(mErasePalette); 3423 palette.setColor (centralWidget()->backgroundRole(), Qt::black); 3424 centralWidget()->setPalette (palette); 3425 centralWidget()->setAutoFillBackground (!aSeamless); 3426 mConsoleStyle = mConsole->frameStyle(); 3427 mConsole->setFrameStyle (QFrame::NoFrame); 3428 mConsole->setMaximumSize (scrGeo.size()); 3429 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3430 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3431 } 3432 else 3433 { 3434 /* Reset the shifting spacers. */ 3435 mShiftingSpacerLeft->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3436 mShiftingSpacerTop->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3437 mShiftingSpacerRight->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3438 mShiftingSpacerBottom->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3439 3440 /* Restore the previous scroll-view minimum size before the exiting 3441 * fullscreen. Required for correct scroll-view and guest display 3442 * update in SDL mode. */ 3443 mConsole->setMinimumSize (mPrevMinSize); 3444 3445 #ifdef Q_WS_MAC 3446 if (aSeamless) 3447 { 3448 /* Please note: All the stuff below has to be done before the 3449 * window switch back to normal size. Qt changes the winId on the 3450 * fullscreen switch and make this stuff useless with the old 3451 * winId. So please be careful on rearrangement of the method 3452 * calls. */ 3453 /* Undo all mac specific installations */ 3454 ::darwinSetShowsWindowTransparent (this, false); 3455 } 3456 #endif 3457 3458 /* Adjust colors and appearance. */ 3459 clearMask(); 3460 centralWidget()->setPalette (mErasePalette); 3461 centralWidget()->setAutoFillBackground (false); 3462 mConsole->setFrameStyle (mConsoleStyle); 3463 mConsole->setMaximumSize (mConsole->sizeHint()); 3464 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3465 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3466 3467 /* Show everything hidden when going fullscreen. */ 3468 foreach (QPointer <QWidget> child, mHiddenChildren) 3469 if (child) child->show(); 3470 mHiddenChildren.clear(); 3471 } 3472 3473 /* Set flag for waiting host resize if it awaited during mode entering */ 3474 if ((mIsFullscreen || mIsSeamless) && (consoleSize != initialSize)) 3475 mIsWaitingModeResize = true; 3476 3477 if (!aOn) 3478 { 3479 /* Animation takes a bit long, the mini toolbar is still disappearing 3480 * when switched to normal mode so hide it completely */ 3481 mMiniToolBar->hide(); 3482 mMiniToolBar->updateDisplay (false, true); 3483 } 3484 3485 /* Toggle qt full-screen mode */ 3486 switchToFullscreen (aOn, aSeamless); 3487 3488 if (aOn) 3489 { 3490 mMiniToolBar->setSeamlessMode (aSeamless); 3491 mMiniToolBar->updateDisplay (true, true); 3492 } 3493 3494 #ifdef Q_WS_MAC 3495 if (aOn && aSeamless) 3496 { 3497 /* Please note: All the stuff below has to be done after the window has 3498 * switched to fullscreen. Qt changes the winId on the fullscreen 3499 * switch and make this stuff useless with the old winId. So please be 3500 * careful on rearrangement of the method calls. */ 3501 ::darwinSetShowsWindowTransparent (this, true); 3502 } 3503 #endif 3504 3505 /* Send guest size hint */ 3506 mConsole->toggleFSMode (consoleSize); 3507 3508 /* Process all console attributes changes and sub-widget hidings */ 3509 qApp->processEvents(); 3510 3511 if (!mIsWaitingModeResize) 3512 onExitFullscreen(); 3513 3514 /* Unlock FS actions locked during modes toggling */ 3515 QTimer::singleShot (300, this, SLOT (unlockActionsSwitch())); 3516 3517 #ifdef Q_WS_MAC /* wasHidden is wrong on the mac it seems. */ 3518 /** @todo figure out what is really wrong here... */ 3519 if (!wasHidden) 3520 show(); 3521 #else 3522 if (wasHidden) 3523 hide(); 3524 #endif 3525 3526 return true; 3527 } 3528 3529 void VBoxConsoleWnd::switchToFullscreen (bool aOn, bool aSeamless) 3530 { 3531 #ifdef Q_WS_MAC 3532 # ifndef QT_MAC_USE_COCOA 3533 /* setWindowState removes the window group connection somehow. So save it 3534 * temporary. */ 3535 WindowGroupRef g = GetWindowGroup (::darwinToNativeWindow (this)); 3536 # endif /* !QT_MAC_USE_COCOA */ 3537 if (aSeamless) 3538 if (aOn) 3539 { 3540 /* Save for later restoring */ 3541 mNormalGeometry = geometry(); 3542 mSavedFlags = windowFlags(); 3543 /* Remove the frame from the window */ 3544 const QRect fullscreen (qApp->desktop()->screenGeometry (qApp->desktop()->screenNumber (this))); 3545 setParent (0, Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); 3546 setGeometry (fullscreen); 3547 /* Set it maximized */ 3548 setWindowState (windowState() ^ Qt::WindowMaximized); 3549 } 3550 else 3551 { 3552 /* Restore old values */ 3553 setParent (0, mSavedFlags); 3554 setGeometry (mNormalGeometry); 3555 } 3556 else 3557 { 3558 /* Here we are going really fullscreen */ 3559 setWindowState (windowState() ^ Qt::WindowFullScreen); 3560 changePresentationMode (VBoxChangePresentationModeEvent(aOn)); 3561 } 3562 3563 # ifndef QT_MAC_USE_COCOA 3564 /* Reassign the correct window group. */ 3565 SetWindowGroup (::darwinToNativeWindow (this), g); 3566 # endif /* !QT_MAC_USE_COCOA */ 3567 #else 3568 NOREF (aOn); 3569 NOREF (aSeamless); 3570 setWindowState (windowState() ^ Qt::WindowFullScreen); 3571 #endif 3572 } 3573 3574 void VBoxConsoleWnd::setViewInSeamlessMode (const QRect &aTargetRect) 3575 { 3576 #ifndef Q_WS_MAC 3577 /* It isn't guaranteed that the guest os set the video mode that 3578 * we requested. So after all the resizing stuff set the clipping 3579 * mask and the spacing shifter to the corresponding values. */ 3580 QDesktopWidget *dtw = QApplication::desktop(); 3581 QRect sRect = dtw->screenGeometry (this); 3582 QRect aRect (aTargetRect); 3583 mMaskShift.scale (aTargetRect.left(), aTargetRect.top(), Qt::IgnoreAspectRatio); 3584 /* Set the clipping mask */ 3585 mStrictedRegion = aRect; 3586 /* Set the shifting spacer */ 3587 mShiftingSpacerLeft->changeSize (RT_ABS (sRect.left() - aRect.left()), 0, 3588 QSizePolicy::Fixed, QSizePolicy::Preferred); 3589 mShiftingSpacerTop->changeSize (0, RT_ABS (sRect.top() - aRect.top()), 3590 QSizePolicy::Preferred, QSizePolicy::Fixed); 3591 mShiftingSpacerRight->changeSize (RT_ABS (sRect.right() - aRect.right()), 0, 3592 QSizePolicy::Fixed, QSizePolicy::Preferred); 3593 mShiftingSpacerBottom->changeSize (0, RT_ABS (sRect.bottom() - aRect.bottom()), 3594 QSizePolicy::Preferred, QSizePolicy::Fixed); 3595 #else // !Q_WS_MAC 3596 NOREF (aTargetRect); 3597 #endif // !Q_WS_MAC 3598 } 3599 3600 /** 3601 * Closes the console view opened by openView(). 3602 * Does nothing if no console view was opened. 3603 */ 3604 void VBoxConsoleWnd::closeView() 3605 { 3606 LogFlowFuncEnter(); 3607 3608 if (!mConsole) 3609 { 3610 LogFlow (("Already closed!\n")); 3611 LogFlowFuncLeave(); 3612 return; 3613 } 3614 3615 mConsole->detach(); 3616 centralWidget()->layout()->removeWidget (mConsole); 3617 delete mConsole; 3618 mConsole = 0; 3619 mSession.Close(); 3620 mSession.detach(); 3621 3622 LogFlowFuncLeave(); 3623 } 3624 3625 #ifdef VBOX_WITH_DEBUGGER_GUI 3626 3627 /** 3628 * Prepare the Debug menu. 3629 */ 3630 void VBoxConsoleWnd::dbgPrepareDebugMenu() 3631 { 3632 /* The "Logging" item. */ 3633 bool fEnabled = false; 3634 bool fChecked = false; 3635 CConsole console = mSession.GetConsole(); 3636 if (console.isOk()) 3637 { 3638 CMachineDebugger cdebugger = console.GetDebugger(); 3639 if (console.isOk()) 3640 { 3641 fEnabled = true; 3642 fChecked = cdebugger.GetLogEnabled() != FALSE; 3643 } 3644 } 3645 if (fEnabled != mDbgLoggingAction->isEnabled()) 3646 mDbgLoggingAction->setEnabled (fEnabled); 3647 if (fChecked != mDbgLoggingAction->isChecked()) 3648 mDbgLoggingAction->setChecked (fChecked); 3649 } 3650 3651 /** 3652 * Called when the Debug->Statistics... menu item is selected. 3653 */ 3654 void VBoxConsoleWnd::dbgShowStatistics() 3655 { 3656 if (dbgCreated()) 3657 mDbgGuiVT->pfnShowStatistics (mDbgGui); 3658 } 3659 3660 /** 3661 * Called when the Debug->Command Line... menu item is selected. 3662 */ 3663 void VBoxConsoleWnd::dbgShowCommandLine() 3664 { 3665 if (dbgCreated()) 3666 mDbgGuiVT->pfnShowCommandLine (mDbgGui); 3667 } 3668 3669 /** 3670 * Called when the Debug->Logging menu item is selected. 3671 */ 3672 void VBoxConsoleWnd::dbgLoggingToggled (bool aState) 3673 { 3674 NOREF(aState); 3675 CConsole console = mSession.GetConsole(); 3676 if (console.isOk()) 3677 { 3678 CMachineDebugger cdebugger = console.GetDebugger(); 3679 if (console.isOk()) 3680 cdebugger.SetLogEnabled (aState); 3681 } 3682 } 3683 3684 /** 3685 * Ensures that the debugger GUI instance is ready. 3686 * 3687 * @returns true if instance is fine and dandy. 3688 * @returns flase if it's not. 3689 */ 3690 bool VBoxConsoleWnd::dbgCreated() 3691 { 3692 if (mDbgGui) 3693 return true; 3694 3695 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 3696 if (hLdrMod == NIL_RTLDRMOD) 3697 return false; 3698 3699 PFNDBGGUICREATE pfnGuiCreate; 3700 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 3701 if (RT_SUCCESS (rc)) 3702 { 3703 ISession *pISession = mSession.raw(); 3704 rc = pfnGuiCreate (pISession, &mDbgGui, &mDbgGuiVT); 3705 if (RT_SUCCESS (rc)) 3706 { 3707 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (mDbgGuiVT->u32Version, DBGGUIVT_VERSION) || 3708 mDbgGuiVT->u32EndVersion == mDbgGuiVT->u32Version) 3709 { 3710 mDbgGuiVT->pfnSetParent (mDbgGui, (QWidget*) this); 3711 mDbgGuiVT->pfnSetMenu (mDbgGui, (QMenu*) mDbgMenu); 3712 dbgAdjustRelativePos(); 3713 return true; 3714 } 3715 3716 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 3717 mDbgGuiVT->u32Version, mDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3718 } 3719 else 3720 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 3721 } 3722 else 3723 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 3724 3725 mDbgGui = 0; 3726 mDbgGuiVT = 0; 3727 return false; 3728 } 3729 3730 /** 3731 * Destroys the debugger GUI instacne if it has been created. 3732 */ 3733 void VBoxConsoleWnd::dbgDestroy() 3734 { 3735 if (mDbgGui) 3736 { 3737 mDbgGuiVT->pfnDestroy (mDbgGui); 3738 mDbgGui = 0; 3739 mDbgGuiVT = 0; 3740 } 3741 } 3742 3743 /** 3744 * Tells the debugger GUI that the console window has moved or been resized. 3745 */ 3746 void VBoxConsoleWnd::dbgAdjustRelativePos() 3747 { 3748 if (mDbgGui) 3749 { 3750 QRect rct = frameGeometry(); 3751 mDbgGuiVT->pfnAdjustRelativePos (mDbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 3752 } 3753 } 3754 3755 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3756 3757 VBoxNetworkDialog::VBoxNetworkDialog (QWidget *aParent, CSession &aSession) 3758 : QIWithRetranslateUI <QDialog> (aParent) 3759 , mSettings (0) 3760 , mSession (aSession) 3761 { 3762 setModal (true); 3763 /* Setup Dialog's options */ 3764 setWindowIcon (QIcon (":/nw_16px.png")); 3765 setSizeGripEnabled (true); 3766 3767 /* Setup main dialog's layout */ 3768 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3769 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3770 mainLayout->setSpacing (10); 3771 3772 /* Setup settings layout */ 3773 mSettings = new VBoxVMSettingsNetworkPage (true); 3774 mSettings->setOrderAfter (this); 3775 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3776 mSettings->getFrom (aSession.GetMachine()); 3777 mainLayout->addWidget (mSettings); 3778 3779 /* Setup button's layout */ 3780 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3781 3782 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3783 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3784 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3785 mainLayout->addWidget (buttonBox); 3786 3787 retranslateUi(); 3788 } 3789 3790 void VBoxNetworkDialog::retranslateUi() 3791 { 3792 setWindowTitle (tr ("Network Adapters")); 3793 } 3794 3795 void VBoxNetworkDialog::accept() 3796 { 3797 mSettings->putBackTo(); 3798 CMachine machine = mSession.GetMachine(); 3799 machine.SaveSettings(); 3800 if (!machine.isOk()) 3801 vboxProblem().cannotSaveMachineSettings (machine); 3802 QDialog::accept(); 3803 } 3804 3805 void VBoxNetworkDialog::showEvent (QShowEvent *aEvent) 3806 { 3807 resize (450, 300); 3808 VBoxGlobal::centerWidget (this, parentWidget()); 3809 setMinimumWidth (400); 3810 QDialog::showEvent (aEvent); 3811 } 3812 3813 VBoxSFDialog::VBoxSFDialog (QWidget *aParent, CSession &aSession) 3814 : QIWithRetranslateUI <QDialog> (aParent) 3815 , mSettings (0) 3816 , mSession (aSession) 3817 { 3818 setModal (true); 3819 /* Setup Dialog's options */ 3820 setWindowIcon (QIcon (":/select_file_16px.png")); 3821 setSizeGripEnabled (true); 3822 3823 /* Setup main dialog's layout */ 3824 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3825 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3826 mainLayout->setSpacing (10); 3827 3828 /* Setup settings layout */ 3829 mSettings = new VBoxVMSettingsSF (MachineType | ConsoleType, this); 3830 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3831 mSettings->getFromConsole (aSession.GetConsole()); 3832 mSettings->getFromMachine (aSession.GetMachine()); 3833 mainLayout->addWidget (mSettings); 3834 3835 /* Setup button's layout */ 3836 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3837 3838 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3839 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3840 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3841 mainLayout->addWidget (buttonBox); 3842 3843 retranslateUi(); 3844 } 3845 3846 void VBoxSFDialog::retranslateUi() 3847 { 3848 setWindowTitle (tr ("Shared Folders")); 3849 } 3850 3851 void VBoxSFDialog::accept() 3852 { 3853 mSettings->putBackToConsole(); 3854 mSettings->putBackToMachine(); 3855 CMachine machine = mSession.GetMachine(); 3856 machine.SaveSettings(); 3857 if (!machine.isOk()) 3858 vboxProblem().cannotSaveMachineSettings (machine); 3859 QDialog::accept(); 3860 } 3861 3862 void VBoxSFDialog::showEvent (QShowEvent *aEvent) 3863 { 3864 resize (450, 300); 3865 VBoxGlobal::centerWidget (this, parentWidget()); 3866 setMinimumWidth (400); 3867 QDialog::showEvent (aEvent); 3868 } 3869 3870 #include "VBoxConsoleWnd.moc" 390 QString testStr = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 391 /* Default to true if it is an empty value */ 392 bool bIsDockIconEnabled = testStr.isEmpty() || testStr == "true"; 393 machineView()->setDockIconEnabled(bIsDockIconEnabled); 394 machineView()->updateDockOverlay(); 395 #endif 396 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass declaration4 * UIMachineWindow class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2009Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef __VBoxConsoleWnd_h__ 24 #define __VBoxConsoleWnd_h__ 25 26 /* Global includes */ 27 #include <QColor> 28 #include <QDialog> 29 #include <QMainWindow> 30 #include <QMap> 31 #include <QMenu> 32 #include <QPointer> 23 #ifndef __UIMachineWindow_h__ 24 #define __UIMachineWindow_h__ 33 25 34 26 /* Local includes */ 35 #include "COMDefs.h" 36 #include "QIWithRetranslateUI.h" 37 #include "VBoxProblemReporter.h" 38 #include "VBoxHelpActions.h" 39 40 #ifdef VBOX_WITH_DEBUGGER_GUI 41 # include <VBox/dbggui.h> 42 #endif 43 #ifdef Q_WS_MAC 44 # include <ApplicationServices/ApplicationServices.h> 45 # ifndef QT_MAC_USE_COCOA 46 # include <Carbon/Carbon.h> 47 # endif /* !QT_MAC_USE_COCOA */ 48 #endif 27 #include "UIMachineDefs.h" 49 28 50 29 /* Global forwards */ 51 class QAction; 52 class QActionGroup; 53 class QLabel; 54 class QSpacerItem; 55 class QIWidgetValidator; 30 class QWidget; 56 31 57 32 /* Local forwards */ 58 class QIMenu; 59 class QIStateIndicator; 60 class VBoxChangeDockIconUpdateEvent; 61 class VBoxChangePresentationModeEvent; 62 class VBoxConsoleView; 63 class VBoxMiniToolBar; 64 class VBoxSwitchMenu; 65 class VBoxUSBMenu; 33 class UIMachineLogic; 34 class UIMachineView; 66 35 67 class VBoxConsoleWnd : public QIWithRetranslateUI2 <QMainWindow>36 class UIMachineWindow 68 37 { 69 Q_OBJECT;70 71 38 public: 72 39 73 VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent = 0, Qt::WindowFlags aFlags = Qt::Window);74 virtual ~VBoxConsoleWnd();40 /* Factory function to create required machine window child: */ 41 static UIMachineWindow* create(UIMachineLogic *pMachineLogic, UIVisualStateType visualStateType); 75 42 76 bool isWindowMaximized() const 77 { 78 #ifdef Q_WS_MAC 79 /* On Mac OS X we didn't really jump to the fullscreen mode but 80 * maximize the window. This situation has to be considered when 81 * checking for maximized or fullscreen mode. */ 82 return !isTrueSeamless() && QMainWindow::isMaximized(); 83 #else /* Q_WS_MAC */ 84 return QMainWindow::isMaximized(); 85 #endif /* Q_WS_MAC */ 86 } 87 bool isWindowFullScreen() const 88 { 89 #ifdef Q_WS_MAC 90 /* On Mac OS X we didn't really jump to the fullscreen mode but 91 * maximize the window. This situation has to be considered when 92 * checking for maximized or fullscreen mode. */ 93 return isTrueFullscreen() || isTrueSeamless(); 94 #else /* Q_WS_MAC */ 95 return QMainWindow::isFullScreen(); 96 #endif /* Q_WS_MAC */ 97 } 98 bool isTrueFullscreen() const { return mIsFullscreen; } 99 bool isTrueSeamless() const { return mIsSeamless; } 43 /* Abstract slot to close machine window: */ 44 virtual void sltTryClose() = 0; 100 45 101 KMachineState machineState() const { return mMachineState; } 102 103 bool openView (const CSession &aSession); 104 105 void setMouseIntegrationLocked (bool aDisabled); 106 107 void popupMainMenu (bool aCenter); 108 109 void installGuestAdditionsFrom (const QString &aSource); 110 111 void setMask (const QRegion &aRegion); 112 void clearMask(); 113 114 /* informs that the guest display is resized */ 115 void onDisplayResize (ulong aHeight, ulong aWidth); 116 117 #ifdef VBOX_WITH_VIDEOHWACCEL 118 /* used for obtaining the extradata settings */ 119 CSession &session() { return mSession; } 120 #endif 121 signals: 122 123 void closing(); 46 /* Public getters: */ 47 virtual UIMachineLogic* machineLogic() { return m_pMachineLogic; } 48 virtual QWidget* machineWindow() { return m_pMachineWindow; } 49 virtual UIMachineView* machineView() { return m_pMachineView; } 124 50 125 51 protected: 126 52 127 bool event (QEvent *aEvent); 128 void closeEvent (QCloseEvent *aEvent); 129 #ifdef Q_WS_X11 130 bool x11Event (XEvent *aEvent); 131 #endif 53 /* Common machine window constructor: */ 54 UIMachineWindow(UIMachineLogic *pMachineLogic); 55 virtual ~UIMachineWindow(); 132 56 133 void retranslateUi(); 57 /* Translate routine: */ 58 void retranslateWindow(); 134 59 135 private slots: 60 /* Update routines: */ 61 virtual void updateAppearanceOf(int iElement); 136 62 137 void finalizeOpenView();138 void tryClose();63 /* Common machine window event handlers: */ 64 void closeEvent(QCloseEvent *pEvent); 139 65 140 void vmFullscreen (bool aOn); 141 void vmSeamless (bool aOn); 142 void vmAutoresizeGuest (bool aOn); 143 void vmAdjustWindow(); 144 void vmDisableMouseIntegration (bool aOff); 145 void vmTypeCAD(); 146 #ifdef Q_WS_X11 147 void vmTypeCABS(); 148 #endif 149 void vmTakeSnapshot(); 150 void vmShowInfoDialog(); 151 void vmReset(); 152 void vmPause (bool aOn); 153 void vmACPIShutdown(); 154 void vmClose(); 66 /* Protected getters: */ 67 const QString& defaultWindowTitle() const { return m_strWindowTitlePrefix; } 155 68 156 void devicesSwitchVrdp (bool aOn); 157 void devicesOpenNetworkDialog(); 158 void devicesOpenSFDialog(); 159 void devicesInstallGuestAdditions(); 160 161 void prepareStorageMenu(); 162 void prepareNetworkMenu(); 163 void prepareSFMenu(); 164 165 void mountMedium(); 166 void switchUSB (QAction *aAction); 167 168 void showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent); 169 170 void updateDeviceLights(); 171 void updateMachineState (KMachineState aState); 172 void updateMouseState (int aState); 173 void updateAdditionsState (const QString &aVersion, bool aActive, 174 bool aSeamlessSupported, bool aGraphicsSupported); 175 void updateNetworkAdaptersState(); 176 void updateUsbState(); 177 void updateMediaDriveState (VBoxDefs::MediumType aType); 178 void updateSharedFoldersState(); 179 180 void onExitFullscreen(); 181 void unlockActionsSwitch(); 182 183 void mtExitMode(); 184 void mtCloseVM(); 185 void mtMaskUpdate(); 186 187 void changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent); 188 void changePresentationMode (const VBoxChangePresentationModeEvent &aEvent); 189 void processGlobalSettingChange (const char *aPublicName, const char *aName); 190 191 #ifdef VBOX_WITH_DEBUGGER_GUI 192 void dbgPrepareDebugMenu(); 193 void dbgShowStatistics(); 194 void dbgShowCommandLine(); 195 void dbgLoggingToggled (bool aBool); 196 #endif 69 /* Protected variables: */ 70 QWidget *m_pMachineWindow; 71 UIMachineView *m_pMachineView; 197 72 198 73 private: 199 74 200 enum /* Stuff */ 201 { 202 HardDiskStuff = 0x01, 203 DVDStuff = 0x02, 204 FloppyStuff = 0x04, 205 PauseAction = 0x08, 206 NetworkStuff = 0x10, 207 DisableMouseIntegrAction = 0x20, 208 Caption = 0x40, 209 USBStuff = 0x80, 210 VRDPStuff = 0x100, 211 SharedFolderStuff = 0x200, 212 VirtualizationStuff = 0x400, 213 AllStuff = 0xFFFF, 214 }; 75 /* Prepare helpers: */ 76 void prepareWindowIcon(); 77 void loadWindowSettings(); 215 78 216 void checkRequiredFeatures(); 217 void activateUICustomizations(); 79 /* Cleanup helpers: */ 80 //void saveWindowSettings(); 81 //void cleanupWindowIcon(); 218 82 219 void updateAppearanceOf (int aElement); 83 /* Getter variables: */ 84 UIMachineLogic *m_pMachineLogic; 220 85 221 bool toggleFullscreenMode (bool aOn, bool aSeamless); 222 void switchToFullscreen (bool aOn, bool aSeamless); 223 void setViewInSeamlessMode (const QRect &aTargetRect); 224 225 void closeView(); 226 227 #ifdef VBOX_WITH_DEBUGGER_GUI 228 bool dbgCreated(); 229 void dbgDestroy(); 230 void dbgAdjustRelativePos(); 231 #endif 232 233 /* COM Variables */ 234 CSession mSession; 235 236 /* Machine State */ 237 KMachineState mMachineState; 238 239 /* Window Variables */ 240 QString mCaptionPrefix; 241 int mConsoleStyle; 242 243 /* Menu items */ 244 QIMenu *mMainMenu; 245 QMenu *mVMMenu; 246 QMenu *mVMMenuMini; 247 QMenu *mDevicesMenu; 248 QMenu *mDevicesCDMenu; 249 QMenu *mDevicesFDMenu; 250 QMenu *mDevicesNetworkMenu; 251 QMenu *mDevicesSFMenu; 252 VBoxUSBMenu *mDevicesUSBMenu; 253 VBoxSwitchMenu *mVmDisMouseIntegrMenu; 254 #if 0 /* todo: allow to setup */ 255 VBoxSwitchMenu *mDevicesVRDPMenu; 256 VBoxSwitchMenu *mVmAutoresizeMenu; 257 #endif 258 #ifdef VBOX_WITH_DEBUGGER_GUI 259 QMenu *mDbgMenu; 260 #endif 261 QMenu *mHelpMenu; 262 263 QActionGroup *mRunningActions; 264 QActionGroup *mRunningOrPausedActions; 265 266 /* Machine actions */ 267 QAction *mVmFullscreenAction; 268 QAction *mVmSeamlessAction; 269 QAction *mVmAutoresizeGuestAction; 270 QAction *mVmAdjustWindowAction; 271 QAction *mVmDisableMouseIntegrAction; 272 QAction *mVmTypeCADAction; 273 #ifdef Q_WS_X11 274 QAction *mVmTypeCABSAction; 275 #endif 276 QAction *mVmTakeSnapshotAction; 277 QAction *mVmShowInformationDlgAction; 278 QAction *mVmResetAction; 279 QAction *mVmPauseAction; 280 QAction *mVmACPIShutdownAction; 281 QAction *mVmCloseAction; 282 283 /* Devices actions */ 284 QAction *mDevicesNetworkDialogAction; 285 QAction *mDevicesSFDialogAction; 286 QAction *mDevicesSwitchVrdpSeparator; 287 QAction *mDevicesSwitchVrdpAction; 288 QAction *mDevicesInstallGuestToolsAction; 289 290 #ifdef VBOX_WITH_DEBUGGER_GUI 291 /* Debugger actions */ 292 QAction *mDbgStatisticsAction; 293 QAction *mDbgCommandLineAction; 294 QAction *mDbgLoggingAction; 295 #endif 296 297 /* Help actions */ 298 VBoxHelpActions mHelpActions; 299 300 /* Widgets */ 301 VBoxConsoleView *mConsole; 302 VBoxMiniToolBar *mMiniToolBar; 303 #ifdef VBOX_WITH_DEBUGGER_GUI 304 /** The handle to the debugger gui. */ 305 PDBGGUI mDbgGui; 306 /** The virtual method table for the debugger GUI. */ 307 PCDBGGUIVT mDbgGuiVT; 308 #endif 309 310 /* Timer to update LEDs */ 311 QTimer *mIdleTimer; 312 313 /* LEDs */ 314 QIStateIndicator *mHDLed; 315 QIStateIndicator *mCDLed; 316 #if 0 /* todo: allow to setup */ 317 QIStateIndicator *mFDLed; 318 #endif 319 QIStateIndicator *mNetLed; 320 QIStateIndicator *mUSBLed; 321 QIStateIndicator *mSFLed; 322 QIStateIndicator *mVirtLed; 323 QIStateIndicator *mMouseLed; 324 QIStateIndicator *mHostkeyLed; 325 QWidget *mHostkeyLedContainer; 326 QLabel *mHostkeyName; 327 #if 0 /* todo: allow to setup */ 328 QIStateIndicator *mVrdpLed; 329 QIStateIndicator *mAutoresizeLed; 330 #endif 331 332 /* Normal Mode */ 333 QRect mNormalGeo; 334 335 /* Fullscreen/Seamless Mode */ 336 QList < QPointer <QWidget> > mHiddenChildren; 337 QSpacerItem *mShiftingSpacerLeft; 338 QSpacerItem *mShiftingSpacerTop; 339 QSpacerItem *mShiftingSpacerRight; 340 QSpacerItem *mShiftingSpacerBottom; 341 QPalette mErasePalette; 342 QSize mPrevMinSize; 343 QSize mMaskShift; 344 QRegion mStrictedRegion; 345 #ifdef Q_WS_WIN 346 QRegion mPrevRegion; 347 #endif 348 #ifdef Q_WS_MAC 349 //QRegion mCurrRegion; 350 # ifndef QT_MAC_USE_COCOA 351 //EventHandlerRef mDarwinRegionEventHandlerRef; 352 # endif 353 /* For seamless maximizing */ 354 QRect mNormalGeometry; 355 Qt::WindowFlags mSavedFlags; 356 /* For the fade effect if the the window goes fullscreen */ 357 CGDisplayFadeReservationToken mFadeToken; 358 #endif 359 360 /* Different bool flags */ 361 bool mIsOpenViewFinished : 1; 362 bool mIsFirstTimeStarted : 1; 363 bool mIsAutoSaveMedia : 1; 364 bool mNoAutoClose : 1; 365 bool mIsFullscreen : 1; 366 bool mIsSeamless : 1; 367 bool mIsSeamlessSupported : 1; 368 bool mIsGraphicsSupported : 1; 369 bool mIsWaitingModeResize : 1; 370 bool mWasMax : 1; 86 /* Helper variables: */ 87 QString m_strWindowTitlePrefix; 371 88 }; 372 89 373 /* We want to make the first action highlighted but not 374 * selected, but Qt makes the both or neither one of this, 375 * so, just move the focus to the next eligible object, 376 * which will be the first menu action. This little 377 * subclass made only for that purpose. */ 378 class QIMenu : public QMenu 379 { 380 Q_OBJECT; 381 382 public: 383 384 QIMenu (QWidget *aParent) : QMenu (aParent) {} 385 386 void selectFirstAction() { QMenu::focusNextChild(); } 387 }; 388 389 class VBoxSettingsPage; 390 class VBoxNetworkDialog : public QIWithRetranslateUI <QDialog> 391 { 392 Q_OBJECT; 393 394 public: 395 396 VBoxNetworkDialog (QWidget *aParent, CSession &aSession); 397 398 protected: 399 400 void retranslateUi(); 401 402 protected slots: 403 404 virtual void accept(); 405 406 protected: 407 408 void showEvent (QShowEvent *aEvent); 409 410 private: 411 412 VBoxSettingsPage *mSettings; 413 CSession &mSession; 414 }; 415 416 class VBoxVMSettingsSF; 417 class VBoxSFDialog : public QIWithRetranslateUI <QDialog> 418 { 419 Q_OBJECT; 420 421 public: 422 423 VBoxSFDialog (QWidget *aParent, CSession &aSession); 424 425 protected: 426 427 void retranslateUi(); 428 429 protected slots: 430 431 virtual void accept(); 432 433 protected: 434 435 void showEvent (QShowEvent *aEvent); 436 437 private: 438 439 VBoxVMSettingsSF *mSettings; 440 CSession &mSession; 441 }; 442 443 #endif // __VBoxConsoleWnd_h__ 90 #endif // __UIMachineWindow_h__ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass implementation4 * UIMachineLogicNormal class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010 Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 23 23 /* Global includes */ 24 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 25 # include "precomp.h" 26 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 27 #include <QActionGroup> 28 #include <QDesktopWidget> 29 #include <QDir> 30 #include <QFileInfo> 31 #include <QMenuBar> 32 #include <QProgressBar> 24 #include <QMenu> 33 25 #include <QTimer> 34 26 35 #ifdef Q_WS_X11 36 # include <QX11Info> 37 #endif 27 /* Local includes */ 28 #include "VBoxGlobal.h" 29 #include "VBoxProblemReporter.h" 30 31 #include "UIFirstRunWzd.h" 32 33 #include "UIActionsPool.h" 34 #include "UIMachineLogicNormal.h" 35 #include "UIMachineWindow.h" 36 #include "UIMachineView.h" 37 38 UIMachineLogicNormal::UIMachineLogicNormal(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool) 39 : UIMachineLogic(pParent, session, pActionsPool, UIVisualStateType_Normal) 40 { 41 /* Prepare action connections: */ 42 prepareActionConnections(); 43 44 /* Prepare normal machine window: */ 45 prepareMachineWindow(); 46 } 47 48 UIMachineLogicNormal::~UIMachineLogicNormal() 49 { 50 /* Cleanup normal machine window: */ 51 cleanupMachineWindow(); 52 } 53 54 void UIMachineLogicNormal::sltPrepareNetworkAdaptersMenu() 55 { 56 QMenu *menu = qobject_cast<QMenu*>(sender()); 57 AssertMsg(menu, ("This slot should be called only on Network Adapters Menu show!\n")); 58 menu->clear(); 59 menu->addAction(actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)); 60 } 61 62 void UIMachineLogicNormal::sltPrepareSharedFoldersMenu() 63 { 64 QMenu *menu = qobject_cast<QMenu*>(sender()); 65 AssertMsg(menu, ("This slot should be called only on Shared Folders Menu show!\n")); 66 menu->clear(); 67 menu->addAction(actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog)); 68 } 69 70 void UIMachineLogicNormal::updateAppearanceOf(int iElement) 71 { 72 /* Update parent-class elements: */ 73 UIMachineLogic::updateAppearanceOf(iElement); 74 } 75 76 void UIMachineLogicNormal::prepareActionConnections() 77 { 78 connect(actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->menu(), SIGNAL(aboutToShow()), 79 this, SLOT(sltPrepareNetworkAdaptersMenu())); 80 connect(actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu(), SIGNAL(aboutToShow()), 81 this, SLOT(sltPrepareSharedFoldersMenu())); 82 } 83 84 void UIMachineLogicNormal::prepareMachineWindow() 85 { 86 if (machineWindowWrapper()) 87 return; 88 38 89 #ifdef Q_WS_MAC 39 # include <QPainter> 40 #endif 41 42 /* Local includes */ 43 #include "QIFileDialog.h" 44 #include "QIHotKeyEdit.h" 45 #include "QIHttp.h" 46 #include "QIStateIndicator.h" 47 #include "QIStatusBar.h" 48 #include "QIWidgetValidator.h" 49 #include "QIHotKeyEdit.h" 50 #include "VBoxConsoleWnd.h" 51 #include "VBoxConsoleView.h" 52 #include "VBoxCloseVMDlg.h" 53 #include "VBoxDownloaderWgt.h" 54 #include "VBoxGlobal.h" 55 #include "VBoxMediaManagerDlg.h" 56 #include "VBoxMiniToolBar.h" 57 #include "VBoxProblemReporter.h" 58 #include "VBoxTakeSnapshotDlg.h" 59 #include "UIFirstRunWzd.h" 60 #include "VBoxVMSettingsNetwork.h" 61 #include "VBoxVMSettingsSF.h" 62 #include "VBoxVMInformationDlg.h" 63 64 #ifdef Q_WS_X11 65 # include <X11/Xlib.h> 66 # include <XKeyboard.h> 67 #endif 68 #ifdef Q_WS_MAC 69 # include "VBoxUtils.h" 70 # include "VBoxIChatTheaterWrapper.h" 71 # include <ApplicationServices/ApplicationServices.h> 72 #endif 73 #ifdef VBOX_WITH_DEBUGGER_GUI 74 # include <VBox/err.h> 75 # include <iprt/ldr.h> 76 #endif 77 78 #include <VBox/VMMDev.h> /** @todo @bugref{4084} */ 79 #include <iprt/buildconfig.h> 80 #include <iprt/param.h> 81 #include <iprt/path.h> 82 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 83 84 /* Global forwards */ 85 extern void qt_set_sequence_auto_mnemonic (bool on); 86 87 /** class StatusTipEvent 88 * 89 * The StatusTipEvent class is an auxiliary QEvent class 90 * for carrying statusTip text of non-QAction menu item's. 91 * This event is posted then the menu item is highlighted but 92 * processed later in VBoxConsoleWnd::event() handler to 93 * avoid statusBar messaging collisions. 94 */ 95 class StatusTipEvent : public QEvent 96 { 97 public: 98 enum { Type = QEvent::User + 10 }; 99 StatusTipEvent (const QString &aTip) 100 : QEvent ((QEvent::Type) Type), mTip (aTip) {} 101 102 QString mTip; 103 }; 104 105 class VBoxAdditionsDownloader : public VBoxDownloaderWgt 106 { 107 Q_OBJECT; 108 109 public: 110 111 VBoxAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 112 : VBoxDownloaderWgt (aSource, aTarget) 113 , mAction (aAction) 114 { 115 mAction->setEnabled (false); 116 retranslateUi(); 117 } 118 119 void start() 120 { 121 acknowledgeStart(); 122 } 123 124 protected: 125 126 void retranslateUi() 127 { 128 mCancelButton->setText (tr ("Cancel")); 129 mProgressBar->setToolTip (tr ("Downloading the VirtualBox Guest Additions " 130 "CD image from <nobr><b>%1</b>...</nobr>") 131 .arg (mSource.toString())); 132 mCancelButton->setToolTip (tr ("Cancel the VirtualBox Guest " 133 "Additions CD image download")); 134 } 135 136 private slots: 137 138 void downloadFinished (bool aError) 139 { 140 if (aError) 141 VBoxDownloaderWgt::downloadFinished (aError); 142 else 143 { 144 QByteArray receivedData (mHttp->readAll()); 145 /* Serialize the incoming buffer into the .iso image. */ 146 while (true) 147 { 148 QFile file (mTarget); 149 if (file.open (QIODevice::WriteOnly)) 150 { 151 file.write (receivedData); 152 file.close(); 153 if (vboxProblem().confirmMountAdditions (mSource.toString(), 154 QDir::toNativeSeparators (mTarget))) 155 vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 156 QTimer::singleShot (0, this, SLOT (suicide())); 157 break; 158 } 159 else 160 { 161 vboxProblem().message (window(), VBoxProblemReporter::Error, 162 tr ("<p>Failed to save the downloaded file as " 163 "<nobr><b>%1</b>.</nobr></p>") 164 .arg (QDir::toNativeSeparators (mTarget))); 165 } 166 167 QString target = QIFileDialog::getExistingDirectory ( 168 QFileInfo (mTarget).absolutePath(), this, 169 tr ("Select folder to save Guest Additions image to"), true); 170 if (target.isNull()) 171 QTimer::singleShot (0, this, SLOT (suicide())); 172 else 173 mTarget = QDir (target).absoluteFilePath (QFileInfo (mTarget).fileName()); 174 } 175 } 176 } 177 178 void suicide() 179 { 180 QStatusBar *sb = qobject_cast <QStatusBar*> (parent()); 181 Assert (sb); 182 sb->removeWidget (this); 183 mAction->setEnabled (true); 184 VBoxDownloaderWgt::suicide(); 185 } 186 187 private: 188 189 bool confirmDownload() 190 { 191 return vboxProblem().confirmDownloadAdditions (mSource.toString(), 192 mHttp->lastResponse().contentLength()); 193 } 194 195 void warnAboutError (const QString &aError) 196 { 197 return vboxProblem().cannotDownloadGuestAdditions (mSource.toString(), aError); 198 } 199 200 QAction *mAction; 201 }; 202 203 struct MountTarget 204 { 205 MountTarget() : name (QString ("")), port (0), device (0), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 206 MountTarget (const QString &aName, LONG aPort, LONG aDevice) 207 : name (aName), port (aPort), device (aDevice), id (QString()), type (VBoxDefs::MediumType_Invalid) {} 208 MountTarget (const QString &aName, LONG aPort, LONG aDevice, const QString &aId) 209 : name (aName), port (aPort), device (aDevice), id (aId), type (VBoxDefs::MediumType_Invalid) {} 210 MountTarget (const QString &aName, LONG aPort, LONG aDevice, VBoxDefs::MediumType aType) 211 : name (aName), port (aPort), device (aDevice), id (QString()), type (aType) {} 212 QString name; 213 LONG port; 214 LONG device; 215 QString id; 216 VBoxDefs::MediumType type; 217 }; 218 Q_DECLARE_METATYPE (MountTarget); 219 220 int searchMaxSnapshotIndex (const CMachine &aMachine, const CSnapshot &aSnapshot, const QString &aNameTemplate) 221 { 222 int maxIndex = 0; 223 QRegExp regExp (QString ("^") + aNameTemplate.arg ("([0-9]+)") + QString ("$")); 224 if (!aSnapshot.isNull()) 225 { 226 /* Check the current snapshot name */ 227 QString name = aSnapshot.GetName(); 228 int pos = regExp.indexIn (name); 229 if (pos != -1) 230 maxIndex = regExp.cap (1).toInt() > maxIndex ? regExp.cap (1).toInt() : maxIndex; 231 /* Traversing all the snapshot children */ 232 foreach (const CSnapshot &child, aSnapshot.GetChildren()) 233 { 234 int maxIndexOfChildren = searchMaxSnapshotIndex (aMachine, child, aNameTemplate); 235 maxIndex = maxIndexOfChildren > maxIndex ? maxIndexOfChildren : maxIndex; 236 } 237 } 238 return maxIndex; 239 } 240 241 /** \class VBoxConsoleWnd 242 * 243 * The VBoxConsoleWnd class is a VM console window, one of two main VBox 244 * GUI windows. 245 * 246 * This window appears when the user starts the virtual machine. It 247 * contains the VBoxConsoleView widget that acts as a console of the 248 * running virtual machine. 249 */ 250 251 /** 252 * Constructs the VM console window. 253 * 254 * @param aSelf pointer to a variable where to store |this| right after 255 * this object's constructor is called (necessary to avoid 256 * recursion in VBoxGlobal::consoleWnd()) 257 */ 258 VBoxConsoleWnd::VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent, Qt::WindowFlags aFlags /* = Qt::Window */) 259 : QIWithRetranslateUI2 <QMainWindow> (aParent, aFlags) 260 /* Machine State */ 261 , mMachineState (KMachineState_Null) 262 /* Window Variables */ 263 , mConsoleStyle (0) 264 /* Menu Items */ 265 , mMainMenu (0) 266 , mVMMenu (0) 267 , mVMMenuMini (0) 268 , mDevicesMenu (0) 269 , mDevicesCDMenu (0) 270 , mDevicesFDMenu (0) 271 , mDevicesNetworkMenu (0) 272 , mDevicesSFMenu (0) 273 , mDevicesUSBMenu (0) 274 , mVmDisMouseIntegrMenu (0) 275 #if 0 /* TODO: Allow to setup status-bar! */ 276 , mDevicesVRDPMenu (0) 277 , mVmAutoresizeMenu (0) 278 #endif 279 #ifdef VBOX_WITH_DEBUGGER_GUI 280 , mDbgMenu (0) 281 #endif 282 , mHelpMenu (0) 283 /* Action Groups */ 284 , mRunningActions (0) 285 , mRunningOrPausedActions (0) 286 /* Machine Menu Actions */ 287 , mVmFullscreenAction (0) 288 , mVmSeamlessAction (0) 289 , mVmAutoresizeGuestAction (0) 290 , mVmAdjustWindowAction (0) 291 , mVmDisableMouseIntegrAction (0) 292 , mVmTypeCADAction (0) 293 #ifdef Q_WS_X11 294 , mVmTypeCABSAction (0) 295 #endif 296 , mVmTakeSnapshotAction (0) 297 , mVmShowInformationDlgAction (0) 298 , mVmResetAction (0) 299 , mVmPauseAction (0) 300 , mVmACPIShutdownAction (0) 301 , mVmCloseAction (0) 302 /* Device Menu Actions */ 303 , mDevicesNetworkDialogAction (0) 304 , mDevicesSFDialogAction (0) 305 , mDevicesSwitchVrdpSeparator (0) 306 , mDevicesSwitchVrdpAction (0) 307 , mDevicesInstallGuestToolsAction (0) 308 #ifdef VBOX_WITH_DEBUGGER_GUI 309 /* Debug Menu Actions */ 310 , mDbgStatisticsAction (0) 311 , mDbgCommandLineAction (0) 312 , mDbgLoggingAction (0) 313 #endif 314 /* Widgets */ 315 , mConsole (0) 316 , mMiniToolBar (0) 317 #ifdef VBOX_WITH_DEBUGGER_GUI 318 , mDbgGui (0) 319 , mDbgGuiVT (0) 320 #endif 321 /* LED Update Timer */ 322 , mIdleTimer (new QTimer (this)) 323 /* LEDs */ 324 , mHDLed (0) 325 , mCDLed (0) 326 #if 0 /* TODO: Allow to setup status-bar! */ 327 , mFDLed (0) 328 #endif 329 , mNetLed (0) 330 , mUSBLed (0) 331 , mSFLed (0) 332 , mVirtLed (0) 333 , mMouseLed (0) 334 , mHostkeyLed (0) 335 , mHostkeyLedContainer (0) 336 , mHostkeyName (0) 337 #if 0 /* TODO: Allow to setup status-bar! */ 338 , mVrdpLed (0) 339 , mAutoresizeLed (0) 340 #endif 341 , mIsOpenViewFinished (false) 342 , mIsFirstTimeStarted (false) 343 , mIsAutoSaveMedia (true) 344 , mNoAutoClose (false) 345 , mIsFullscreen (false) 346 , mIsSeamless (false) 347 , mIsSeamlessSupported (false) 348 , mIsGraphicsSupported (false) 349 , mIsWaitingModeResize (false) 350 , mWasMax (false) 351 { 352 if (aSelf) 353 *aSelf = this; 354 355 /* Cache IMedium data! */ 356 vboxGlobal().startEnumeratingMedia(); 357 358 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 359 /* The default application icon (will change to the VM-specific icon in 360 * openView()). On Win32, it's built-in to the executable. On Mac OS X the 361 * icon referenced in info.plist is used. */ 362 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 363 #endif 364 365 /* Ensure status bar is created */ 366 setStatusBar (new QIStatusBar (this)); 367 368 /* A group for all actions that are enabled only when the VM is running. 369 * Note that only actions whose enabled state depends exclusively on the 370 * execution state of the VM are added to this group. */ 371 mRunningActions = new QActionGroup (this); 372 mRunningActions->setExclusive (false); 373 374 /* A group for all actions that are enabled when the VM is running or 375 * paused. Note that only actions whose enabled state depends exclusively 376 * on the execution state of the VM are added to this group. */ 377 mRunningOrPausedActions = new QActionGroup (this); 378 mRunningOrPausedActions->setExclusive (false); 379 380 /* VM menu actions */ 381 mVmFullscreenAction = new QAction (this); 382 mVmFullscreenAction->setIcon (VBoxGlobal::iconSetOnOff ( 383 ":/fullscreen_on_16px.png", ":/fullscreen_16px.png", 384 ":/fullscreen_on_disabled_16px.png", ":/fullscreen_disabled_16px.png")); 385 mVmFullscreenAction->setCheckable (true); 386 387 mVmSeamlessAction = new QAction (this); 388 mVmSeamlessAction->setIcon (VBoxGlobal::iconSetOnOff ( 389 ":/seamless_on_16px.png", ":/seamless_16px.png", 390 ":/seamless_on_disabled_16px.png", ":/seamless_disabled_16px.png")); 391 mVmSeamlessAction->setCheckable (true); 392 393 mVmAutoresizeGuestAction = new QAction (mRunningActions); 394 mVmAutoresizeGuestAction->setIcon (VBoxGlobal::iconSetOnOff ( 395 ":/auto_resize_on_on_16px.png", ":/auto_resize_on_16px.png", 396 ":/auto_resize_on_on_disabled_16px.png", ":/auto_resize_on_disabled_16px.png")); 397 mVmAutoresizeGuestAction->setCheckable (true); 398 mVmAutoresizeGuestAction->setEnabled (false); 399 400 mVmAdjustWindowAction = new QAction (this); 401 mVmAdjustWindowAction->setIcon (VBoxGlobal::iconSet ( 402 ":/adjust_win_size_16px.png", ":/adjust_win_size_disabled_16px.png")); 403 404 mVmDisableMouseIntegrAction = new QAction (this); 405 mVmDisableMouseIntegrAction->setIcon (VBoxGlobal::iconSetOnOff ( 406 ":/mouse_can_seamless_on_16px.png", ":/mouse_can_seamless_16px.png", 407 ":/mouse_can_seamless_on_disabled_16px.png", ":/mouse_can_seamless_disabled_16px.png")); 408 mVmDisableMouseIntegrAction->setCheckable (true); 409 410 mVmTypeCADAction = new QAction (mRunningActions); 411 mVmTypeCADAction->setIcon (VBoxGlobal::iconSet ( 412 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 413 414 #if defined(Q_WS_X11) 415 mVmTypeCABSAction = new QAction (mRunningActions); 416 mVmTypeCABSAction->setIcon (VBoxGlobal::iconSet ( 417 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 418 #endif 419 420 mVmTakeSnapshotAction = new QAction (mRunningOrPausedActions); 421 mVmTakeSnapshotAction->setIcon (VBoxGlobal::iconSet ( 422 ":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png")); 423 424 mVmShowInformationDlgAction = new QAction (this); 425 mVmShowInformationDlgAction->setIcon (VBoxGlobal::iconSet ( 426 ":/session_info_16px.png", ":/session_info_disabled_16px.png")); 427 428 mVmResetAction = new QAction (mRunningActions); 429 mVmResetAction->setIcon (VBoxGlobal::iconSet ( 430 ":/reset_16px.png", ":/reset_disabled_16px.png")); 431 432 mVmPauseAction = new QAction (this); 433 mVmPauseAction->setIcon (VBoxGlobal::iconSet ( 434 ":/pause_16px.png", ":/pause_disabled_16px.png")); 435 mVmPauseAction->setCheckable (true); 436 437 mVmACPIShutdownAction = new QAction (mRunningActions); 438 mVmACPIShutdownAction->setIcon (VBoxGlobal::iconSet ( 439 ":/acpi_16px.png", ":/acpi_disabled_16px.png")); 440 441 mVmCloseAction = new QAction (this); 442 mVmCloseAction->setMenuRole (QAction::QuitRole); 443 mVmCloseAction->setIcon (VBoxGlobal::iconSet (":/exit_16px.png")); 444 445 /* Devices menu actions */ 446 mDevicesNetworkDialogAction = new QAction (mRunningOrPausedActions); 447 mDevicesNetworkDialogAction->setIcon (VBoxGlobal::iconSet ( 448 ":/nw_16px.png", ":/nw_disabled_16px.png")); 449 450 mDevicesSFDialogAction = new QAction (mRunningOrPausedActions); 451 mDevicesSFDialogAction->setIcon (VBoxGlobal::iconSet ( 452 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")); 453 454 mDevicesSwitchVrdpAction = new QAction (mRunningOrPausedActions); 455 mDevicesSwitchVrdpAction->setIcon (VBoxGlobal::iconSetOnOff ( 456 ":/vrdp_on_16px.png", ":/vrdp_16px.png", 457 ":/vrdp_on_disabled_16px.png", ":/vrdp_disabled_16px.png")); 458 mDevicesSwitchVrdpAction->setCheckable (true); 459 460 mDevicesInstallGuestToolsAction = new QAction (mRunningActions); 461 mDevicesInstallGuestToolsAction->setIcon (VBoxGlobal::iconSet ( 462 ":/guesttools_16px.png", ":/guesttools_disabled_16px.png")); 463 464 #ifdef VBOX_WITH_DEBUGGER_GUI 465 /* Debug menu actions */ 466 if (vboxGlobal().isDebuggerEnabled()) 467 { 468 mDbgStatisticsAction = new QAction (this); 469 mDbgCommandLineAction = new QAction (this); 470 if (vboxGlobal().getDebuggerModule()== NIL_RTLDRMOD) 471 { 472 mDbgStatisticsAction->setEnabled (false); 473 mDbgCommandLineAction->setEnabled (false); 474 } 475 mDbgLoggingAction = new QAction (this); 476 mDbgLoggingAction->setCheckable (true); 477 } 478 else 479 { 480 mDbgStatisticsAction = 0; 481 mDbgCommandLineAction = 0; 482 mDbgLoggingAction = 0; 483 } 484 #endif 485 486 /* Help menu actions */ 487 mHelpActions.setup (this); 488 489 /* Menu Items */ 490 mMainMenu = new QIMenu (this); 491 mDevicesCDMenu = new QMenu (this); 492 mDevicesFDMenu = new QMenu (this); 493 mDevicesNetworkMenu = new QMenu (this); 494 mDevicesSFMenu = new QMenu (this); 495 mDevicesUSBMenu = new VBoxUSBMenu (this); 496 497 /* Machine submenu */ 498 mVMMenu = menuBar()->addMenu (QString::null); 499 mMainMenu->addMenu (mVMMenu); 500 mVmDisMouseIntegrMenu = new VBoxSwitchMenu (mVMMenu, mVmDisableMouseIntegrAction, true); 501 #if 0 /* TODO: Allow to setup status-bar! */ 502 mVmAutoresizeMenu = new VBoxSwitchMenu (mVMMenu, mVmAutoresizeGuestAction); 503 #endif 504 505 mVMMenu->addAction (mVmFullscreenAction); 506 mVMMenu->addAction (mVmSeamlessAction); 507 mVMMenu->addAction (mVmAutoresizeGuestAction); 508 mVMMenu->addAction (mVmAdjustWindowAction); 509 mVMMenu->addSeparator(); 510 mVMMenu->addAction (mVmDisableMouseIntegrAction); 511 mVMMenu->addSeparator(); 512 mVMMenu->addAction (mVmTypeCADAction); 513 #ifdef Q_WS_X11 514 mVMMenu->addAction (mVmTypeCABSAction); 515 #endif 516 mVMMenu->addSeparator(); 517 mVMMenu->addAction (mVmTakeSnapshotAction); 518 mVMMenu->addSeparator(); 519 mVMMenu->addAction (mVmShowInformationDlgAction); 520 mVMMenu->addSeparator(); 521 mVMMenu->addAction (mVmResetAction); 522 mVMMenu->addAction (mVmPauseAction); 523 mVMMenu->addAction (mVmACPIShutdownAction); 524 #ifndef Q_WS_MAC 525 mVMMenu->addSeparator(); 90 /* We have to make sure that we are getting the front most process. 91 * This is necessary for Qt versions > 4.3.3: */ 92 ProcessSerialNumber psn = { 0, kCurrentProcess }; 93 ::SetFrontProcess(&psn); 526 94 #endif /* Q_WS_MAC */ 527 mVMMenu->addAction (mVmCloseAction); 528 529 /* Devices submenu */ 530 mDevicesMenu = menuBar()->addMenu (QString::null); 531 mMainMenu->addMenu (mDevicesMenu); 532 533 mDevicesCDMenu->setIcon (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png")); 534 mDevicesFDMenu->setIcon (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png")); 535 mDevicesUSBMenu->setIcon (VBoxGlobal::iconSet (":/usb_16px.png", ":/usb_disabled_16px.png")); 536 537 mDevicesMenu->addMenu (mDevicesCDMenu); 538 mDevicesMenu->addMenu (mDevicesFDMenu); 539 mDevicesMenu->addAction (mDevicesNetworkDialogAction); 540 mDevicesMenu->addAction (mDevicesSFDialogAction); 541 mDevicesMenu->addMenu (mDevicesUSBMenu); 542 543 #if 0 /* TODO: Allow to setup status-bar! */ 544 mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, mDevicesSwitchVrdpAction); 545 #endif 546 mDevicesSwitchVrdpSeparator = mDevicesMenu->addSeparator(); 547 mDevicesMenu->addAction (mDevicesSwitchVrdpAction); 548 549 mDevicesMenu->addSeparator(); 550 mDevicesMenu->addAction (mDevicesInstallGuestToolsAction); 551 552 #ifdef VBOX_WITH_DEBUGGER_GUI 553 /* Debug submenu */ 554 if (vboxGlobal().isDebuggerEnabled()) 555 { 556 mDbgMenu = menuBar()->addMenu (QString::null); 557 mMainMenu->addMenu (mDbgMenu); 558 mDbgMenu->addAction (mDbgStatisticsAction); 559 mDbgMenu->addAction (mDbgCommandLineAction); 560 mDbgMenu->addAction (mDbgLoggingAction); 561 } 562 else 563 mDbgMenu = 0; 564 #endif 565 566 /* Help submenu */ 567 mHelpMenu = menuBar()->addMenu (QString::null); 568 mMainMenu->addMenu (mHelpMenu); 569 mHelpActions.addTo (mHelpMenu); 570 571 /* Machine submenu for mini-toolbar */ 572 mVMMenuMini = new QMenu (this); 573 mVMMenuMini->addAction (mVmTypeCADAction); 574 #ifdef Q_WS_X11 575 mVMMenuMini->addAction (mVmTypeCABSAction); 576 #endif 577 mVMMenuMini->addSeparator(); 578 mVMMenuMini->addAction (mVmTakeSnapshotAction); 579 mVMMenuMini->addSeparator(); 580 mVMMenuMini->addAction (mVmShowInformationDlgAction); 581 mVMMenuMini->addSeparator(); 582 mVMMenuMini->addAction (mVmResetAction); 583 mVMMenuMini->addAction (mVmPauseAction); 584 mVMMenuMini->addAction (mVmACPIShutdownAction); 585 586 /* Status bar */ 587 QWidget *indicatorBox = new QWidget; 588 QHBoxLayout *indicatorBoxHLayout = new QHBoxLayout (indicatorBox); 589 VBoxGlobal::setLayoutMargin (indicatorBoxHLayout, 0); 590 indicatorBoxHLayout->setSpacing (5); 591 592 /* i/o devices */ 593 mHDLed = new QIStateIndicator (KDeviceActivity_Idle); 594 mHDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/hd_16px.png")); 595 mHDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/hd_read_16px.png")); 596 mHDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/hd_write_16px.png")); 597 mHDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/hd_disabled_16px.png")); 598 indicatorBoxHLayout->addWidget (mHDLed); 599 mCDLed = new QIStateIndicator (KDeviceActivity_Idle); 600 mCDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/cd_16px.png")); 601 mCDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/cd_read_16px.png")); 602 mCDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/cd_write_16px.png")); 603 mCDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/cd_disabled_16px.png")); 604 indicatorBoxHLayout->addWidget (mCDLed); 605 #if 0 /* TODO: Allow to setup status-bar! */ 606 mFDLed = new QIStateIndicator (KDeviceActivity_Idle); 607 mFDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/fd_16px.png")); 608 mFDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/fd_read_16px.png")); 609 mFDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/fd_write_16px.png")); 610 mFDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/fd_disabled_16px.png")); 611 indicatorBoxHLayout->addWidget (mFDLed); 612 #endif 613 mNetLed = new QIStateIndicator (KDeviceActivity_Idle); 614 mNetLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/nw_16px.png")); 615 mNetLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/nw_read_16px.png")); 616 mNetLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/nw_write_16px.png")); 617 mNetLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/nw_disabled_16px.png")); 618 indicatorBoxHLayout->addWidget (mNetLed); 619 mUSBLed = new QIStateIndicator (KDeviceActivity_Idle); 620 mUSBLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/usb_16px.png")); 621 mUSBLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/usb_read_16px.png")); 622 mUSBLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/usb_write_16px.png")); 623 mUSBLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/usb_disabled_16px.png")); 624 indicatorBoxHLayout->addWidget (mUSBLed); 625 mSFLed = new QIStateIndicator (KDeviceActivity_Idle); 626 mSFLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/shared_folder_16px.png")); 627 mSFLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/shared_folder_read_16px.png")); 628 mSFLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/shared_folder_write_16px.png")); 629 mSFLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/shared_folder_disabled_16px.png")); 630 indicatorBoxHLayout->addWidget (mSFLed); 631 632 /* virtualization */ 633 mVirtLed = new QIStateIndicator (0); 634 mVirtLed->setStateIcon (0, QPixmap (":/vtx_amdv_disabled_16px.png")); 635 mVirtLed->setStateIcon (1, QPixmap (":/vtx_amdv_16px.png")); 636 indicatorBoxHLayout->addWidget (mVirtLed); 637 638 QFrame *separator = new QFrame(); 639 separator->setFrameStyle (QFrame::VLine | QFrame::Sunken); 640 indicatorBoxHLayout->addWidget (separator); 641 642 /* mouse */ 643 mMouseLed = new QIStateIndicator (0); 644 mMouseLed->setStateIcon (0, QPixmap (":/mouse_disabled_16px.png")); 645 mMouseLed->setStateIcon (1, QPixmap (":/mouse_16px.png")); 646 mMouseLed->setStateIcon (2, QPixmap (":/mouse_seamless_16px.png")); 647 mMouseLed->setStateIcon (3, QPixmap (":/mouse_can_seamless_16px.png")); 648 mMouseLed->setStateIcon (4, QPixmap (":/mouse_can_seamless_uncaptured_16px.png")); 649 indicatorBoxHLayout->addWidget (mMouseLed); 650 651 /* host key */ 652 mHostkeyLedContainer = new QWidget; 653 QHBoxLayout *hostkeyLEDContainerLayout = new QHBoxLayout (mHostkeyLedContainer); 654 VBoxGlobal::setLayoutMargin (hostkeyLEDContainerLayout, 0); 655 hostkeyLEDContainerLayout->setSpacing (3); 656 indicatorBoxHLayout->addWidget (mHostkeyLedContainer); 657 658 mHostkeyLed = new QIStateIndicator (0); 659 mHostkeyLed->setStateIcon (0, QPixmap (":/hostkey_16px.png")); 660 mHostkeyLed->setStateIcon (1, QPixmap (":/hostkey_captured_16px.png")); 661 mHostkeyLed->setStateIcon (2, QPixmap (":/hostkey_pressed_16px.png")); 662 mHostkeyLed->setStateIcon (3, QPixmap (":/hostkey_captured_pressed_16px.png")); 663 hostkeyLEDContainerLayout->addWidget (mHostkeyLed); 664 mHostkeyName = new QLabel (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 665 hostkeyLEDContainerLayout->addWidget (mHostkeyName); 666 667 #if 0 /* TODO: Allow to setup status-bar! */ 668 /* VRDP Led */ 669 mVrdpLed = new QIStateIndicator (0, indicatorBox, "mVrdpLed", Qt::WNoAutoErase); 670 mVrdpLed->setStateIcon (0, QPixmap (":/vrdp_disabled_16px.png")); 671 mVrdpLed->setStateIcon (1, QPixmap (":/vrdp_16px.png")); 672 /* Auto-Resize LED */ 673 mAutoresizeLed = new QIStateIndicator (1, indicatorBox, "mAutoresizeLed", Qt::WNoAutoErase); 674 mAutoresizeLed->setStateIcon (0, QPixmap (":/auto_resize_off_disabled_16px.png")); 675 mAutoresizeLed->setStateIcon (1, QPixmap (":/auto_resize_off_16px.png")); 676 mAutoresizeLed->setStateIcon (2, QPixmap (":/auto_resize_on_disabled_16px.png")); 677 mAutoresizeLed->setStateIcon (3, QPixmap (":/auto_resize_on_16px.png")); 678 #endif 679 680 /* add to statusbar */ 681 statusBar()->addPermanentWidget (indicatorBox, 0); 682 683 /* Retranslate UI */ 684 retranslateUi(); 685 686 setWindowTitle (mCaptionPrefix); 687 688 /* Connections */ 689 connect (mVmFullscreenAction, SIGNAL (toggled (bool)), this, SLOT (vmFullscreen (bool))); 690 connect (mVmSeamlessAction, SIGNAL (toggled (bool)), this, SLOT (vmSeamless (bool))); 691 connect (mVmAutoresizeGuestAction, SIGNAL (toggled (bool)), this, SLOT (vmAutoresizeGuest (bool))); 692 connect (mVmAdjustWindowAction, SIGNAL (triggered()), this, SLOT (vmAdjustWindow())); 693 connect (mVmDisableMouseIntegrAction, SIGNAL (toggled (bool)), this, SLOT (vmDisableMouseIntegration (bool))); 694 connect (mVmTypeCADAction, SIGNAL (triggered()), this, SLOT (vmTypeCAD())); 695 #ifdef Q_WS_X11 696 connect (mVmTypeCABSAction, SIGNAL (triggered()), this, SLOT (vmTypeCABS())); 697 #endif 698 connect (mVmTakeSnapshotAction, SIGNAL (triggered()), this, SLOT (vmTakeSnapshot())); 699 connect (mVmShowInformationDlgAction, SIGNAL (triggered()), this, SLOT (vmShowInfoDialog())); 700 connect (mVmResetAction, SIGNAL (triggered()), this, SLOT (vmReset())); 701 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 702 connect (mVmACPIShutdownAction, SIGNAL (triggered()), this, SLOT (vmACPIShutdown())); 703 connect (mVmCloseAction, SIGNAL (triggered()), this, SLOT (vmClose())); 704 705 connect (mDevicesCDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 706 connect (mDevicesFDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 707 connect (mDevicesNetworkMenu, SIGNAL (aboutToShow()), this, SLOT (prepareNetworkMenu())); 708 connect (mDevicesSFMenu, SIGNAL (aboutToShow()), this, SLOT (prepareSFMenu())); 709 connect (mDevicesUSBMenu, SIGNAL(triggered (QAction *)), this, SLOT(switchUSB (QAction *))); 710 711 connect (mDevicesNetworkDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenNetworkDialog())); 712 connect (mDevicesSFDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenSFDialog())); 713 connect (mDevicesSwitchVrdpAction, SIGNAL (toggled (bool)), this, SLOT (devicesSwitchVrdp (bool))); 714 connect (mDevicesInstallGuestToolsAction, SIGNAL (triggered()), this, SLOT (devicesInstallGuestAdditions())); 715 716 connect (mCDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 717 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 718 #if 0 /* TODO: Allow to setup status-bar! */ 719 connect (mFDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 720 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 721 #endif 722 connect (mNetLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 723 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 724 connect (mUSBLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 725 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 726 connect (mSFLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 727 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 728 connect (mMouseLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 729 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 730 #if 0 /* TODO: Allow to setup status-bar! */ 731 connect (mVrdpLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 732 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 733 connect (mAutoresizeLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 734 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 735 #endif 736 737 /* Watch global settings changes */ 738 connect (&vboxGlobal().settings(), SIGNAL (propertyChanged (const char *, const char *)), 739 this, SLOT (processGlobalSettingChange (const char *, const char *))); 740 #ifdef Q_WS_MAC 741 connect (&vboxGlobal(), SIGNAL (dockIconUpdateChanged (const VBoxChangeDockIconUpdateEvent &)), 742 this, SLOT (changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &))); 743 connect (&vboxGlobal(), SIGNAL (presentationModeChanged (const VBoxChangePresentationModeEvent &)), 744 this, SLOT (changePresentationMode (const VBoxChangePresentationModeEvent &))); 745 #endif 746 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 if (mDbgMenu) 749 connect (mDbgMenu, SIGNAL (aboutToShow()), this, SLOT (dbgPrepareDebugMenu())); 750 if (mDbgStatisticsAction) 751 connect (mDbgStatisticsAction, SIGNAL (triggered()), this, SLOT (dbgShowStatistics())); 752 if (mDbgCommandLineAction) 753 connect (mDbgCommandLineAction, SIGNAL (triggered()), this, SLOT (dbgShowCommandLine())); 754 if (mDbgLoggingAction) 755 connect (mDbgLoggingAction, SIGNAL (toggled (bool)), this, SLOT (dbgLoggingToggled (bool))); 756 #endif 757 758 #ifdef Q_WS_MAC 759 /* For the status bar on Cocoa */ 760 setUnifiedTitleAndToolBarOnMac (true); 761 # ifdef VBOX_WITH_ICHAT_THEATER 762 // int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 }; 763 // HIWindowChangeAttributes (window, setAttr, 0); 764 initSharedAVManager(); 765 # endif 766 #endif 767 768 mMaskShift.scale (0, 0, Qt::IgnoreAspectRatio); 769 } 770 771 VBoxConsoleWnd::~VBoxConsoleWnd() 772 { 773 closeView(); 774 775 #ifdef VBOX_WITH_DEBUGGER_GUI 776 dbgDestroy(); 777 #endif 778 } 779 780 /** 781 * Opens a new console view to interact with a given VM. 782 * Does nothing if the console view is already opened. 783 * Used by VBoxGlobal::startMachine(), should not be called directly. 784 */ 785 bool VBoxConsoleWnd::openView (const CSession &aSession) 786 { 787 LogFlowFuncEnter(); 788 789 if (mConsole) 790 { 791 LogFlowFunc (("Already opened\n")); 792 LogFlowFuncLeave(); 793 return false; 794 } 795 796 #ifdef Q_WS_MAC 797 /* We have to make sure that we are getting the front most process. This is 798 * necessary for Qt versions > 4.3.3 */ 799 ProcessSerialNumber psn = { 0, kCurrentProcess }; 800 ::SetFrontProcess (&psn); 801 #endif /* Q_WS_MAC */ 802 803 mSession = aSession; 804 805 if (!centralWidget()) 806 { 807 setCentralWidget (new QWidget (this)); 808 QGridLayout *pMainLayout = new QGridLayout (centralWidget()); 809 VBoxGlobal::setLayoutMargin (pMainLayout, 0); 810 pMainLayout->setSpacing (0); 811 812 mShiftingSpacerLeft = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 813 mShiftingSpacerTop = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 814 mShiftingSpacerRight = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 815 mShiftingSpacerBottom = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 816 pMainLayout->addItem (mShiftingSpacerTop, 0, 0, 1, -1); 817 pMainLayout->addItem (mShiftingSpacerLeft, 1, 0); 818 pMainLayout->addItem (mShiftingSpacerRight, 1, 2); 819 pMainLayout->addItem (mShiftingSpacerBottom, 2, 0, 1, -1); 820 } 821 822 mVmPauseAction->setChecked (false); 823 824 CConsole console = mSession.GetConsole(); 825 AssertWrapperOk (mSession); 826 827 CMachine machine = mSession.GetMachine(); 828 829 #ifdef VBOX_WITH_VIDEOHWACCEL 830 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled */ 831 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() 832 && VBoxGlobal::isAcceleration2DVideoAvailable() 833 ; 834 #endif 835 836 mConsole = new VBoxConsoleView (this, console, vboxGlobal().vmRenderMode(), 837 #ifdef VBOX_WITH_VIDEOHWACCEL 838 bAccelerate2DVideo, 839 #endif 840 centralWidget()); 841 qobject_cast <QGridLayout*> (centralWidget()->layout())->addWidget (mConsole, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 842 843 /* Mini toolbar */ 844 bool isActive = !(machine.GetExtraData (VBoxDefs::GUI_ShowMiniToolBar) == "no"); 845 bool isAtTop = (machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAlignment) == "top"); 846 bool isAutoHide = !(machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide) == "off"); 847 QList <QMenu*> menus (QList <QMenu*>() << mVMMenuMini << mDevicesMenu); 848 mMiniToolBar = new VBoxMiniToolBar (centralWidget(), isAtTop ? VBoxMiniToolBar::AlignTop : VBoxMiniToolBar::AlignBottom, 849 isActive, isAutoHide); 850 *mMiniToolBar << menus; 851 connect (mMiniToolBar, SIGNAL (exitAction()), this, SLOT (mtExitMode())); 852 connect (mMiniToolBar, SIGNAL (closeAction()), this, SLOT (mtCloseVM())); 853 connect (mMiniToolBar, SIGNAL (geometryUpdated()), this, SLOT (mtMaskUpdate())); 854 connect (this, SIGNAL (closing()), mMiniToolBar, SLOT (close())); 855 856 activateUICustomizations(); 857 858 /* Set the VM-specific application icon */ 859 /* Not on Mac OS X. The dock icon is handled below. */ 860 #ifndef Q_WS_MAC 861 setWindowIcon (vboxGlobal().vmGuestOSTypeIcon (machine.GetOSTypeId())); 862 #endif 863 864 /* Restore the position of the window and some options */ 865 { 866 QString str = machine.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 867 868 bool ok = false, max = false; 869 int x = 0, y = 0, w = 0, h = 0; 870 x = str.section (',', 0, 0).toInt (&ok); 871 if (ok) 872 y = str.section (',', 1, 1).toInt (&ok); 873 if (ok) 874 w = str.section (',', 2, 2).toInt (&ok); 875 if (ok) 876 h = str.section (',', 3, 3).toInt (&ok); 877 if (ok) 878 max = str.section (',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 879 880 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 881 QApplication::desktop()->availableGeometry (this); 882 883 if (ok /* previous parameters were read correctly */) 884 { 885 mNormalGeo = QRect (x, y, w, h); 886 setGeometry (mNormalGeo); 887 888 /* Normalize to the optimal size */ 889 mConsole->normalizeGeometry (true /* adjustPosition */); 890 891 if (max) 892 { 893 /* Maximize if needed */ 894 setWindowState (windowState() | Qt::WindowMaximized); 895 mWasMax = max; 896 } 897 } 898 else 899 { 900 /* Normalize to the optimal size */ 901 mConsole->normalizeGeometry (true /* adjustPosition */); 902 903 /* Move newly created window to the screen center. */ 904 mNormalGeo = geometry(); 905 mNormalGeo.moveCenter (ar.center()); 906 setGeometry (mNormalGeo); 907 } 908 909 show(); 910 911 /* Process show & possible maximize events */ 912 qApp->processEvents(); 913 914 mVmSeamlessAction->setEnabled (false); 915 str = machine.GetExtraData (VBoxDefs::GUI_Seamless); 916 if (str == "on") 917 mVmSeamlessAction->setChecked (true); 918 919 str = machine.GetExtraData (VBoxDefs::GUI_AutoresizeGuest); 920 if (str != "off") 921 mVmAutoresizeGuestAction->setChecked (true); 922 923 str = machine.GetExtraData (VBoxDefs::GUI_FirstRun); 924 if (str == "yes") 925 mIsFirstTimeStarted = true; 926 else if (!str.isEmpty()) 927 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 928 929 str = machine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime); 930 if (str == "no") 931 mIsAutoSaveMedia = false; 932 933 /* Check if one of extended modes to be activated on loading */ 934 QString fsMode = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 935 QString slMode = machine.GetExtraData (VBoxDefs::GUI_Seamless); 936 bool extendedMode = fsMode == "on" || slMode == "on"; 937 938 /* If one of extended modes to be loaded we have to ignore default 939 * console resize event which will come from VGA Device on loading. */ 940 if (extendedMode) 941 mConsole->requestToResize (QSize (w, h - menuBar()->height() - statusBar()->height())); 942 } 943 944 /* initialize storage stuff */ 945 int cdDevicesCount = 0; 946 int fdDevicesCount = 0; 947 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 948 foreach (const CMediumAttachment &attachment, attachments) 949 { 950 if (attachment.GetType() == KDeviceType_DVD) 951 ++ cdDevicesCount; 952 if (attachment.GetType() == KDeviceType_Floppy) 953 ++ fdDevicesCount; 954 } 955 mDevicesCDMenu->menuAction()->setData (cdDevicesCount); 956 mDevicesFDMenu->menuAction()->setData (fdDevicesCount); 957 mDevicesCDMenu->menuAction()->setVisible (cdDevicesCount); 958 mDevicesFDMenu->menuAction()->setVisible (fdDevicesCount); 959 960 /* initialize usb stuff */ 961 CUSBController usbctl = machine.GetUSBController(); 962 if (usbctl.isNull()) 963 { 964 /* hide usb_menu & usb_separator & usb_status_led */ 965 mDevicesUSBMenu->setVisible (false); 966 mUSBLed->setHidden (true); 967 } 968 else 969 { 970 bool isUSBEnabled = usbctl.GetEnabled(); 971 mDevicesUSBMenu->setEnabled (isUSBEnabled); 972 mDevicesUSBMenu->setConsole (console); 973 mUSBLed->setState (isUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null); 974 } 975 976 /* initialize vrdp stuff */ 977 CVRDPServer vrdpsrv = machine.GetVRDPServer(); 978 if (vrdpsrv.isNull()) 979 { 980 /* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */ 981 mDevicesSwitchVrdpAction->setVisible (false); 982 mDevicesSwitchVrdpSeparator->setVisible (false); 983 #if 0 /* TODO: Allow to setup status-bar! */ 984 mVrdpLed->setHidden (true); 985 #endif 986 } 987 988 /* start an idle timer that will update device lighths */ 989 connect (mIdleTimer, SIGNAL (timeout()), SLOT (updateDeviceLights())); 990 mIdleTimer->start (50); 991 992 connect (mConsole, SIGNAL (mouseStateChanged (int)), this, SLOT (updateMouseState (int))); 993 connect (mConsole, SIGNAL (keyboardStateChanged (int)), mHostkeyLed, SLOT (setState (int))); 994 connect (mConsole, SIGNAL (machineStateChanged (KMachineState)), this, SLOT (updateMachineState (KMachineState))); 995 connect (mConsole, SIGNAL (additionsStateChanged (const QString&, bool, bool, bool)), 996 this, SLOT (updateAdditionsState (const QString &, bool, bool, bool))); 997 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), 998 this, SLOT (updateMediaDriveState (VBoxDefs::MediumType))); 999 connect (mConsole, SIGNAL (usbStateChange()), this, SLOT (updateUsbState())); 1000 connect (mConsole, SIGNAL (networkStateChange()), this, SLOT (updateNetworkAdaptersState())); 1001 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateSharedFoldersState())); 1002 1003 #ifdef Q_WS_MAC 1004 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 1005 /* Default to true if it is an empty value */ 1006 bool f = (testStr.isEmpty() || testStr == "true"); 1007 mConsole->setDockIconEnabled (f); 1008 mConsole->updateDockOverlay(); 1009 #endif 1010 1011 /* set the correct initial mMachineState value */ 1012 mMachineState = console.GetState(); 1013 1014 mConsole->normalizeGeometry (false /* adjustPosition */); 1015 1016 updateAppearanceOf (AllStuff); 95 96 m_pMachineWindowContainer = UIMachineWindow::create(this, visualStateType()); 97 98 /* Get the correct initial machineState() value */ 99 setMachineState(session().GetConsole().GetState()); 100 101 /* Update all the stuff: */ 102 updateAppearanceOf(UIVisualElement_AllStuff); 1017 103 1018 104 if (vboxGlobal().settings().autoCapture()) 1019 105 vboxProblem().remindAboutAutoCapture(); 1020 106 1021 /* 1022 * The further startup procedure should be done after we leave this method 1023 * and enter the main event loop in main(), because it may result into 1024 * showing various modal dialogs that will process events from within 1025 * this method that in turn can lead to various side effects like this 1026 * window is closed before this method returns, etc. 1027 */ 1028 1029 QTimer::singleShot (0, this, SLOT (finalizeOpenView())); 1030 1031 LogFlowFuncLeave(); 1032 return true; 1033 } 1034 1035 void VBoxConsoleWnd::setMouseIntegrationLocked (bool aDisabled) 1036 { 1037 mVmDisableMouseIntegrAction->setChecked (false); 1038 mVmDisableMouseIntegrAction->setEnabled (aDisabled); 1039 } 1040 1041 /** 1042 * Shows up and activates the popup version of the main menu. 1043 * 1044 * @param aCenter If @a true, center the popup menu on the screen, otherwise 1045 * show it at the current mouse pointer location. 1046 */ 1047 void VBoxConsoleWnd::popupMainMenu (bool aCenter) 1048 { 1049 QPoint pos = QCursor::pos(); 1050 if (aCenter) 1051 { 1052 QRect deskGeo = QApplication::desktop()->screenGeometry (this); 1053 QRect popGeo = mMainMenu->frameGeometry(); 1054 popGeo.moveCenter (QPoint (deskGeo.width() / 2, deskGeo.height() / 2)); 1055 pos = popGeo.topLeft(); 1056 } 1057 else 1058 { 1059 /* put the menu's bottom right corner to the pointer's hotspot point */ 1060 pos.setX (pos.x() - mMainMenu->frameGeometry().width()); 1061 pos.setY (pos.y() - mMainMenu->frameGeometry().height()); 1062 } 1063 1064 mMainMenu->popup (pos); 1065 mMainMenu->selectFirstAction(); 1066 #ifdef Q_WS_WIN 1067 mMainMenu->activateWindow(); 1068 #endif 1069 } 1070 1071 void VBoxConsoleWnd::installGuestAdditionsFrom (const QString &aSource) 1072 { 1073 CVirtualBox vbox = vboxGlobal().virtualBox(); 1074 QString uuid; 1075 1076 CMedium image = vbox.FindDVDImage (aSource); 1077 if (image.isNull()) 1078 { 1079 image = vbox.OpenDVDImage (aSource, uuid); 1080 if (vbox.isOk()) 1081 uuid = image.GetId(); 1082 } 1083 else 1084 uuid = image.GetId(); 1085 1086 if (!vbox.isOk()) 1087 return vboxProblem().cannotOpenMedium (this, vbox, VBoxDefs::MediumType_DVD, aSource); 1088 1089 Assert (!uuid.isNull()); 1090 CMachine m = mSession.GetMachine(); 1091 1092 QString ctrName; 1093 LONG ctrPort = -1, ctrDevice = -1; 1094 /* Searching for the first suitable slot */ 1095 { 1096 CStorageControllerVector controllers = m.GetStorageControllers(); 1097 int i = 0; 1098 while (i < controllers.size() && ctrName.isNull()) 1099 { 1100 CStorageController controller = controllers [i]; 1101 CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController (controller.GetName()); 1102 int j = 0; 1103 while (j < attachments.size() && ctrName.isNull()) 1104 { 1105 CMediumAttachment attachment = attachments [j]; 1106 if (attachment.GetType() == KDeviceType_DVD) 1107 { 1108 ctrName = controller.GetName(); 1109 ctrPort = attachment.GetPort(); 1110 ctrDevice = attachment.GetDevice(); 1111 } 1112 ++ j; 1113 } 1114 ++ i; 1115 } 1116 } 1117 1118 if (!ctrName.isNull()) 1119 { 1120 bool isMounted = false; 1121 1122 /* Mount medium to the predefined port/device */ 1123 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, false /* force */); 1124 if (m.isOk()) 1125 isMounted = true; 1126 else 1127 { 1128 /* Ask for force mounting */ 1129 if (vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 1130 { 1131 /* Force mount medium to the predefined port/device */ 1132 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, true /* force */); 1133 if (m.isOk()) 1134 isMounted = true; 1135 else 1136 vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, false /* retry? */); 1137 } 1138 } 1139 1140 /* Save medium mounted at runtime */ 1141 if (isMounted && mIsAutoSaveMedia) 1142 { 1143 m.SaveSettings(); 1144 if (!m.isOk()) 1145 vboxProblem().cannotSaveMachineSettings (m); 1146 } 1147 } 1148 else 1149 vboxProblem().cannotMountGuestAdditions (m.GetName()); 1150 } 1151 1152 void VBoxConsoleWnd::setMask (const QRegion &aRegion) 1153 { 1154 QRegion region = aRegion; 1155 1156 /* The global mask shift cause of toolbars and such things. */ 1157 region.translate (mMaskShift.width(), mMaskShift.height()); 1158 1159 /* Including mini toolbar area */ 1160 QRegion toolBarRegion (mMiniToolBar->mask()); 1161 toolBarRegion.translate (mMiniToolBar->mapToGlobal (toolBarRegion.boundingRect().topLeft()) - QPoint (1, 0)); 1162 region += toolBarRegion; 1163 1164 /* Restrict the drawing to the available space on the screen. 1165 * (The &operator is better than the previous used -operator, 1166 * because this excludes space around the real screen also. 1167 * This is necessary for the mac.) */ 1168 region &= mStrictedRegion; 1169 1170 #ifdef Q_WS_WIN 1171 QRegion difference = mPrevRegion.subtract (region); 1172 1173 /* Region offset calculation */ 1174 int fleft = 0, ftop = 0; 1175 1176 /* Visible region calculation */ 1177 HRGN newReg = CreateRectRgn (0, 0, 0, 0); 1178 CombineRgn (newReg, region.handle(), 0, RGN_COPY); 1179 OffsetRgn (newReg, fleft, ftop); 1180 1181 /* Invisible region calculation */ 1182 HRGN diffReg = CreateRectRgn (0, 0, 0, 0); 1183 CombineRgn (diffReg, difference.handle(), 0, RGN_COPY); 1184 OffsetRgn (diffReg, fleft, ftop); 1185 1186 /* Set the current visible region and clean the previous */ 1187 SetWindowRgn (winId(), newReg, FALSE); 1188 RedrawWindow (0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 1189 RedrawWindow (mConsole->viewport()->winId(), 0, 0, RDW_INVALIDATE); 1190 1191 mPrevRegion = region; 1192 #elif defined (Q_WS_MAC) 1193 # if defined (VBOX_GUI_USE_QUARTZ2D) 1194 if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) 1195 { 1196 /* If we are using the Quartz2D backend we have to trigger 1197 * an repaint only. All the magic clipping stuff is done 1198 * in the paint engine. */ 1199 ::darwinWindowInvalidateShape (mConsole->viewport()); 1200 } 1201 else 1202 # endif 1203 { 1204 /* This is necessary to avoid the flicker by an mask update. 1205 * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html 1206 * for the hint. 1207 * There *must* be a better solution. */ 1208 if (!region.isEmpty()) 1209 region |= QRect (0, 0, 1, 1); 1210 // /* Save the current region for later processing in the darwin event handler. */ 1211 // mCurrRegion = region; 1212 // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately 1213 // * this command flushes a copy of the backbuffer to the screen after the new 1214 // * mask is set. This leads into a missplaced drawing of the content. Currently 1215 // * no alternative to this and also this is not 100% perfect. */ 1216 // repaint(); 1217 // qApp->processEvents(); 1218 // /* Now force the reshaping of the window. This is definitly necessary. */ 1219 // ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId())); 1220 QMainWindow::setMask (region); 1221 // HIWindowInvalidateShadow (::darwinToWindowRef (mConsole->viewport())); 1222 } 1223 #else 1224 QMainWindow::setMask (region); 1225 #endif 1226 } 1227 1228 void VBoxConsoleWnd::clearMask() 1229 { 1230 #ifdef Q_WS_WIN 1231 SetWindowRgn (winId(), 0, TRUE); 1232 #else 1233 QMainWindow::clearMask(); 1234 #endif 1235 } 1236 1237 void VBoxConsoleWnd::onDisplayResize (ulong aHeight, ulong aWidth) 1238 { 1239 if (mIsSeamless && QApplication::desktop()->availableGeometry (this).size() != QSize (aHeight, aWidth)) 1240 { 1241 mVmSeamlessAction->setChecked (false); 1242 /* should be cleared already, but just in case */ 1243 if (mIsSeamless) 1244 toggleFullscreenMode (false, true); 1245 } 1246 } 1247 1248 1249 bool VBoxConsoleWnd::event (QEvent *aEvent) 1250 { 1251 switch (aEvent->type()) 1252 { 1253 /* By handling every Resize and Move we keep track of the normal 1254 * (non-minimized and non-maximized) window geometry. Shame on Qt 1255 * that it doesn't provide this geometry in its public APIs. */ 1256 1257 case QEvent::Resize: 1258 { 1259 QResizeEvent *re = (QResizeEvent *) aEvent; 1260 1261 if (!mIsWaitingModeResize && !isWindowMaximized() && 1262 !isTrueFullscreen() && !isTrueSeamless()) 1263 { 1264 mNormalGeo.setSize (re->size()); 1265 #ifdef VBOX_WITH_DEBUGGER_GUI 1266 dbgAdjustRelativePos(); 1267 #endif 1268 } 1269 1270 if (mIsWaitingModeResize) 1271 { 1272 if (!mIsFullscreen && !mIsSeamless) 1273 { 1274 mIsWaitingModeResize = false; 1275 QTimer::singleShot (0, this, SLOT (onExitFullscreen())); 1276 } 1277 } 1278 break; 1279 } 1280 case QEvent::Move: 1281 { 1282 if (!isWindowMaximized() && !isTrueFullscreen() && !isTrueSeamless()) 1283 { 1284 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1285 #ifdef VBOX_WITH_DEBUGGER_GUI 1286 dbgAdjustRelativePos(); 1287 #endif 1288 } 1289 break; 1290 } 1291 #ifdef Q_WS_MAC 1292 case QEvent::Paint: 1293 { 1294 if (mIsSeamless) 1295 { 1296 /* Clear the background */ 1297 CGContextClearRect (::darwinToCGContextRef (this), ::darwinToCGRect (frameGeometry())); 1298 } 1299 break; 1300 } 1301 #endif 1302 case StatusTipEvent::Type: 1303 { 1304 StatusTipEvent *ev = (StatusTipEvent*) aEvent; 1305 statusBar()->showMessage (ev->mTip); 1306 break; 1307 } 1308 default: 1309 break; 1310 } 1311 1312 return QMainWindow::event (aEvent); 1313 } 1314 1315 void VBoxConsoleWnd::closeEvent (QCloseEvent *aEvent) 1316 { 1317 LogFlowFuncEnter(); 1318 1319 static const char *kSave = "save"; 1320 static const char *kShutdown = "shutdown"; 1321 static const char *kPowerOff = "powerOff"; 1322 static const char *kDiscardCurState = "discardCurState"; 1323 1324 if (!mConsole) 1325 { 1326 aEvent->accept(); 1327 LogFlowFunc (("Console already destroyed!")); 1328 LogFlowFuncLeave(); 1329 return; 1330 } 1331 1332 switch (mMachineState) 1333 { 1334 case KMachineState_PoweredOff: 1335 case KMachineState_Saved: 1336 case KMachineState_Teleported: 1337 case KMachineState_Aborted: 1338 /* The machine has been already powered off or saved or aborted -- close the window immediately. */ 1339 aEvent->accept(); 1340 break; 1341 1342 default: 1343 /* The machine is in some temporary state like Saving or Stopping. 1344 * Ignore the close event. When it is Stopping, it will be soon closed anyway from updateMachineState(). 1345 * In all other cases, an appropriate progress dialog will be shown within a few seconds. */ 1346 aEvent->ignore(); 1347 break; 1348 1349 case KMachineState_Teleporting: /** @todo Live Migration: Test closing a VM that's being teleported or snapshotted. */ 1350 case KMachineState_LiveSnapshotting: 1351 case KMachineState_Running: 1352 case KMachineState_Paused: 1353 case KMachineState_TeleportingPausedVM: /** @todo Live Migration: Check out this. */ 1354 case KMachineState_Stuck: 1355 /* Start with ignoring the close event */ 1356 aEvent->ignore(); 1357 1358 bool isACPIEnabled = mSession.GetConsole().GetGuestEnteredACPIMode(); 1359 1360 bool success = true; 1361 1362 bool wasPaused = mMachineState == KMachineState_Paused 1363 || mMachineState == KMachineState_Stuck 1364 || mMachineState == KMachineState_TeleportingPausedVM; 1365 if (!wasPaused) 1366 { 1367 /* Suspend the VM and ignore the close event if failed to do so. 1368 * pause() will show the error message to the user. */ 1369 success = mConsole->pause (true); 1370 } 1371 1372 if (success) 1373 { 1374 success = false; 1375 1376 CMachine machine = mSession.GetMachine(); 1377 VBoxCloseVMDlg dlg (this); 1378 QString typeId = machine.GetOSTypeId(); 1379 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 1380 1381 /* Make the Discard checkbox invisible if there are no snapshots */ 1382 dlg.mCbDiscardCurState->setVisible (machine.GetSnapshotCount() > 0); 1383 if (!machine.GetCurrentSnapshot().isNull()) 1384 dlg.mCbDiscardCurState->setText (dlg.mCbDiscardCurState->text().arg (machine.GetCurrentSnapshot().GetName())); 1385 1386 if (mMachineState != KMachineState_Stuck) 1387 { 1388 /* Read the last user's choice for the given VM */ 1389 QStringList lastAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1390 AssertWrapperOk (machine); 1391 if (lastAction [0] == kSave) 1392 { 1393 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1394 dlg.mRbSave->setChecked (true); 1395 dlg.mRbSave->setFocus(); 1396 } 1397 else if (lastAction [0] == kPowerOff || !isACPIEnabled) 1398 { 1399 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1400 dlg.mRbPowerOff->setChecked (true); 1401 dlg.mRbPowerOff->setFocus(); 1402 } 1403 else /* The default is ACPI Shutdown */ 1404 { 1405 dlg.mRbShutdown->setChecked (true); 1406 dlg.mRbShutdown->setFocus(); 1407 } 1408 dlg.mCbDiscardCurState->setChecked (lastAction.count() > 1 && lastAction [1] == kDiscardCurState); 1409 } 1410 else 1411 { 1412 /* The stuck VM can only be powered off; disable anything else and choose PowerOff */ 1413 dlg.mRbSave->setEnabled (false); 1414 dlg.mRbShutdown->setEnabled (false); 1415 dlg.mRbPowerOff->setChecked (true); 1416 } 1417 1418 bool wasShutdown = false; 1419 1420 if (dlg.exec() == QDialog::Accepted) 1421 { 1422 /* Disable auto closure because we want to have a chance to show 1423 * the error dialog on save state / power off failure. */ 1424 mNoAutoClose = true; 1425 1426 CConsole console = mConsole->console(); 1427 1428 if (dlg.mRbSave->isChecked()) 1429 { 1430 CProgress progress = console.SaveState(); 1431 1432 if (console.isOk()) 1433 { 1434 /* Show the "VM saving" progress dialog */ 1435 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1436 if (progress.GetResultCode() != 0) 1437 vboxProblem().cannotSaveMachineState (progress); 1438 else 1439 success = true; 1440 } 1441 else 1442 vboxProblem().cannotSaveMachineState (console); 1443 } 1444 else if (dlg.mRbShutdown->isChecked()) 1445 { 1446 /* Unpause the VM to let it grab the ACPI shutdown event */ 1447 mConsole->pause (false); 1448 /* Prevent the subsequent unpause request */ 1449 wasPaused = true; 1450 /* Signal ACPI shutdown (if there is no ACPI device, the 1451 * operation will fail) */ 1452 console.PowerButton(); 1453 wasShutdown = console.isOk(); 1454 if (!wasShutdown) 1455 vboxProblem().cannotACPIShutdownMachine (console); 1456 /* Success is always false because we never accept the close 1457 * window action when doing ACPI shutdown */ 1458 success = false; 1459 } 1460 else if (dlg.mRbPowerOff->isChecked()) 1461 { 1462 CProgress progress = console.PowerDown(); 1463 1464 if (console.isOk()) 1465 { 1466 /* Show the power down progress dialog */ 1467 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1468 if (progress.GetResultCode() != 0) 1469 vboxProblem().cannotStopMachine (progress); 1470 else 1471 success = true; 1472 } 1473 else 1474 vboxProblem().cannotStopMachine (console); 1475 1476 if (success) 1477 { 1478 /* Note: leave success = true even if we fail to 1479 * discard the current state later -- the console window 1480 * will closed anyway */ 1481 1482 /* Discard the current state if requested */ 1483 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo (&dlg)) 1484 { 1485 CSnapshot snapshot = machine.GetCurrentSnapshot(); 1486 CProgress progress = console.RestoreSnapshot (snapshot); 1487 if (console.isOk()) 1488 { 1489 /* Show the progress dialog */ 1490 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1491 if (progress.GetResultCode() != 0) 1492 vboxProblem().cannotRestoreSnapshot (progress, snapshot.GetName()); 1493 } 1494 else 1495 vboxProblem().cannotRestoreSnapshot (console, snapshot.GetName()); 1496 } 1497 } 1498 } 1499 1500 if (success) 1501 { 1502 /* Accept the close action on success */ 1503 aEvent->accept(); 1504 } 1505 1506 if (success || wasShutdown) 1507 { 1508 /* Read the last user's choice for the given VM */ 1509 QStringList prevAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1510 /* Memorize the last user's choice for the given VM */ 1511 QString lastAction = kPowerOff; 1512 if (dlg.mRbSave->isChecked()) 1513 lastAction = kSave; 1514 else if (dlg.mRbShutdown->isChecked() || 1515 (dlg.mRbPowerOff->isChecked() && prevAction [0] == kShutdown && !isACPIEnabled)) 1516 lastAction = kShutdown; 1517 else if (dlg.mRbPowerOff->isChecked()) 1518 lastAction = kPowerOff; 1519 else 1520 AssertFailed(); 1521 if (dlg.mCbDiscardCurState->isChecked()) 1522 (lastAction += ",") += kDiscardCurState; 1523 machine.SetExtraData (VBoxDefs::GUI_LastCloseAction, lastAction); 1524 AssertWrapperOk (machine); 1525 } 1526 } 1527 } 1528 1529 mNoAutoClose = false; 1530 1531 if ( mMachineState == KMachineState_PoweredOff 1532 || mMachineState == KMachineState_Saved 1533 || mMachineState == KMachineState_Teleported 1534 || mMachineState == KMachineState_Aborted 1535 ) 1536 { 1537 /* The machine has been stopped while showing the Close or the Pause 1538 * failure dialog -- accept the close event immediately. */ 1539 aEvent->accept(); 1540 } 1541 else 1542 { 1543 if (!success) 1544 { 1545 /* Restore the running state if needed */ 1546 if (!wasPaused && mMachineState == KMachineState_Paused) 1547 mConsole->pause (false); 1548 } 1549 } 1550 break; 1551 } 1552 1553 if (aEvent->isAccepted()) 1554 { 1555 #ifndef VBOX_GUI_SEPARATE_VM_PROCESS 1556 vboxGlobal().selectorWnd().show(); 1557 #endif 1558 1559 /* Stop LED update timer */ 1560 mIdleTimer->stop(); 1561 mIdleTimer->disconnect (SIGNAL (timeout()), this, SLOT (updateDeviceLights())); 1562 1563 /* Hide console window */ 1564 hide(); 1565 1566 /* Save the position of the window and some options */ 1567 CMachine machine = mSession.GetMachine(); 1568 QString winPos = QString ("%1,%2,%3,%4") 1569 .arg (mNormalGeo.x()).arg (mNormalGeo.y()) 1570 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 1571 if (isWindowMaximized() || (mIsFullscreen && mWasMax) || (mIsSeamless && mWasMax)) 1572 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowPosition_Max); 1573 1574 machine.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 1575 1576 machine.SetExtraData (VBoxDefs::GUI_Fullscreen, 1577 mVmFullscreenAction->isChecked() ? "on" : "off"); 1578 machine.SetExtraData (VBoxDefs::GUI_Seamless, 1579 mVmSeamlessAction->isChecked() ? "on" : "off"); 1580 machine.SetExtraData (VBoxDefs::GUI_AutoresizeGuest, 1581 mVmAutoresizeGuestAction->isChecked() ? "on" : "off"); 1582 machine.SetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide, 1583 mMiniToolBar->isAutoHide() ? "on" : "off"); 1584 1585 #ifdef VBOX_WITH_DEBUGGER_GUI 1586 /* Close & destroy the debugger GUI */ 1587 dbgDestroy(); 1588 #endif 1589 1590 /* Make sure all events are delievered */ 1591 qApp->processEvents(); 1592 1593 /* Notify all the top-level dialogs about closing */ 1594 emit closing(); 1595 } 1596 1597 LogFlowFunc (("accepted=%d\n", aEvent->isAccepted())); 1598 LogFlowFuncLeave(); 1599 } 1600 1601 #ifdef Q_WS_X11 1602 bool VBoxConsoleWnd::x11Event (XEvent *aEvent) 1603 { 1604 /* Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut, 1605 * WindowActivate and WindowDeactivate Qt events are not properly sent 1606 * on top level window (i.e. this) deactivation. The fix is to substiute 1607 * the mode in FocusOut X11 event structure to NotifyNormal to cause 1608 * Qt to process it as desired. */ 1609 if (mConsole && aEvent->type == FocusOut) 1610 { 1611 if (aEvent->xfocus.mode == NotifyWhileGrabbed && 1612 (aEvent->xfocus.detail == NotifyAncestor || 1613 aEvent->xfocus.detail == NotifyInferior || 1614 aEvent->xfocus.detail == NotifyNonlinear)) 1615 { 1616 aEvent->xfocus.mode = NotifyNormal; 1617 } 1618 } 1619 return false; 1620 } 1621 #endif 1622 1623 /** 1624 * Sets the strings of the subwidgets using the current 1625 * language. 1626 */ 1627 void VBoxConsoleWnd::retranslateUi() 1628 { 1629 #ifdef VBOX_OSE 1630 mCaptionPrefix = tr ("VirtualBox OSE"); 1631 #else 1632 mCaptionPrefix = tr ("Sun VirtualBox"); 1633 #endif 1634 1635 #ifdef VBOX_BLEEDING_EDGE 1636 mCaptionPrefix += tr (" EXPERIMENTAL build %1r%2 - %3").arg (RTBldCfgVersion()).arg (RTBldCfgRevisionStr()).arg (VBOX_BLEEDING_EDGE); 1637 #endif 1638 /* 1639 * Note: All action shortcuts should be added to the menu text in the 1640 * form of "\tHost+<Key>" where <Key> is the shortcut key according 1641 * to regular QKeySequence rules. No translation of the "Host" word is 1642 * allowed (VBoxConsoleView relies on its spelling). setAccel() must not 1643 * be used. Unfortunately on the Mac the "host" string is silently removed 1644 * & the key is created as an global shortcut. So every e.g. F key stroke 1645 * in the vm leads to a menu call of the F entry. Mysteriously the 1646 * associated action isn't started. As a workaround the Host+<key> is 1647 * written in braces after the menu text. 1648 */ 1649 1650 /* VM actions */ 1651 #ifdef Q_WS_MAC 1652 qt_set_sequence_auto_mnemonic (false); 1653 #endif 1654 1655 mVmDisMouseIntegrMenu->setToolTip (tr ("Mouse Integration", "enable/disable...")); 1656 #if 0 /* TODO: Allow to setup status-bar! */ 1657 mVmAutoresizeMenu->setToolTip (tr ("Auto-resize Guest Display", "enable/disable...")); 1658 #endif 1659 1660 mVmFullscreenAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Fullscreen Mode"), "F")); 1661 mVmFullscreenAction->setStatusTip (tr ("Switch to fullscreen mode" )); 1662 1663 mVmSeamlessAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Seam&less Mode"), "L")); 1664 mVmSeamlessAction->setStatusTip (tr ("Switch to seamless desktop integration mode")); 1665 1666 mVmAutoresizeGuestAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Auto-resize &Guest Display"), "G")); 1667 mVmAutoresizeGuestAction->setStatusTip (tr ("Automatically resize the guest display when the " 1668 "window is resized (requires Guest Additions)")); 1669 1670 mVmAdjustWindowAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Adjust Window Size"), "A")); 1671 mVmAdjustWindowAction->setStatusTip (tr ("Adjust window size and position to best fit the guest display")); 1672 1673 /* mVmDisableMouseIntegrAction is set up in updateAppearanceOf() */ 1674 1675 mVmTypeCADAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Del"), "Del")); 1676 mVmTypeCADAction->setStatusTip (tr ("Send the Ctrl-Alt-Del sequence to the virtual machine")); 1677 1678 #if defined(Q_WS_X11) 1679 mVmTypeCABSAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Backspace"), "Backspace")); 1680 mVmTypeCABSAction->setStatusTip (tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine")); 1681 #endif 1682 1683 mVmTakeSnapshotAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Take &Snapshot..."), "S")); 1684 mVmTakeSnapshotAction->setStatusTip (tr ("Take a snapshot of the virtual machine")); 1685 1686 mVmShowInformationDlgAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Session I&nformation Dialog"), "N")); 1687 mVmShowInformationDlgAction->setStatusTip (tr ("Show Session Information Dialog")); 1688 1689 mVmResetAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Reset"), "R")); 1690 mVmResetAction->setStatusTip (tr ("Reset the virtual machine")); 1691 1692 /* mVmPauseAction is set up in updateAppearanceOf() */ 1693 1694 #ifdef Q_WS_MAC 1695 /* Host+H is Hide on the mac */ 1696 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "U")); 1697 #else /* Q_WS_MAC */ 1698 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "H")); 1699 #endif /* !Q_WS_MAC */ 1700 mVmACPIShutdownAction->setStatusTip (tr ("Send the ACPI Power Button press event to the virtual machine")); 1701 1702 mVmCloseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Close..." ), "Q")); 1703 mVmCloseAction->setStatusTip (tr ("Close the virtual machine")); 1704 mVmCloseAction->setMenuRole (QAction::QuitRole); 1705 1706 /* Devices actions */ 1707 mDevicesCDMenu->setTitle (tr ("&CD/DVD Devices")); 1708 mDevicesFDMenu->setTitle (tr ("&Floppy Devices")); 1709 1710 mDevicesNetworkDialogAction->setText (tr ("&Network Adapters...")); 1711 mDevicesNetworkDialogAction->setStatusTip (tr ("Change the settings of network adapters")); 1712 1713 mDevicesSFDialogAction->setText (tr ("&Shared Folders...")); 1714 mDevicesSFDialogAction->setStatusTip (tr ("Create or modify shared folders")); 1715 1716 mDevicesSwitchVrdpAction->setText (tr ("&Remote Display")); 1717 mDevicesSwitchVrdpAction->setStatusTip (tr ("Enable or disable remote desktop (RDP) connections to this machine")); 1718 #if 0 /* TODO: Allow to setup status-bar! */ 1719 mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server", "enable/disable...")); 1720 #endif 1721 1722 mDevicesInstallGuestToolsAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Install Guest Additions..."), "D")); 1723 mDevicesInstallGuestToolsAction->setStatusTip (tr ("Mount the Guest Additions installation image")); 1724 1725 mDevicesUSBMenu->setTitle (tr ("&USB Devices")); 1726 1727 #ifdef VBOX_WITH_DEBUGGER_GUI 1728 /* Debug actions */ 1729 if (mDbgStatisticsAction) 1730 mDbgStatisticsAction->setText (tr ("&Statistics...", "debug action")); 1731 if (mDbgCommandLineAction) 1732 mDbgCommandLineAction->setText (tr ("&Command Line...", "debug action")); 1733 if (mDbgLoggingAction) 1734 mDbgLoggingAction->setText (tr ("&Logging...", "debug action")); 1735 #endif 1736 1737 /* Help actions */ 1738 mHelpActions.retranslateUi(); 1739 1740 /* Main menu & seamless popup menu */ 1741 mVMMenu->setTitle (tr ("&Machine")); 1742 // mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png")); 1743 1744 mVMMenuMini->setTitle (tr ("&Machine")); 1745 1746 mDevicesMenu->setTitle (tr ("&Devices")); 1747 // mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png")); 1748 1749 #ifdef VBOX_WITH_DEBUGGER_GUI 1750 if (vboxGlobal().isDebuggerEnabled()) 1751 mDbgMenu->setTitle (tr ("De&bug")); 1752 #endif 1753 mHelpMenu->setTitle (tr ("&Help")); 1754 // mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png")); 1755 1756 /* Status bar widgets */ 1757 mMouseLed->setToolTip ( 1758 tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>" 1759 "<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>" 1760 "<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>" 1761 "<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>" 1762 "<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>" 1763 "<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>" 1764 "Note that the mouse integration feature requires Guest Additions to be installed in the guest OS.")); 1765 mHostkeyLed->setToolTip ( 1766 tr ("Indicates whether the keyboard is captured by the guest OS " 1767 "(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>).")); 1768 mHostkeyName->setToolTip ( 1769 tr ("Shows the currently assigned Host key.<br>" 1770 "This key, when pressed alone, toggles the keyboard and mouse " 1771 "capture state. It can also be used in combination with other keys " 1772 "to quickly perform actions from the main menu.")); 1773 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 1774 1775 #if 0 /* TODO: Allow to setup status-bar! */ 1776 mAutoresizeLed->setToolTip ( 1777 tr ("Indicates whether the guest display auto-resize function is On " 1778 "(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). " 1779 "Note that this function requires Guest Additions to be installed in the guest OS.")); 1780 #endif 1781 1782 updateAppearanceOf (AllStuff); 1783 } 1784 1785 void VBoxConsoleWnd::finalizeOpenView() 1786 { 1787 LogFlowFuncEnter(); 1788 1789 /* Notify the console scroll-view about the console-window is opened. */ 1790 mConsole->onViewOpened(); 1791 1792 bool saved = mMachineState == KMachineState_Saved; 1793 1794 CMachine machine = mSession.GetMachine(); 1795 CConsole console = mConsole->console(); 1796 1797 if (mIsFirstTimeStarted) 1798 { 1799 UIFirstRunWzd wzd (this, machine); 107 /* Notify the console scroll-view about the console-window is opened: */ 108 machineWindowWrapper()->machineView()->onViewOpened(); 109 110 bool saved = machineState() == KMachineState_Saved; 111 112 CMachine machine = session().GetMachine(); 113 CConsole console = session().GetConsole(); 114 115 if (isFirstTimeStarted()) 116 { 117 UIFirstRunWzd wzd(machineWindowWrapper()->machineWindow(), machine); 1800 118 wzd.exec(); 1801 119 … … 1805 123 } 1806 124 1807 /* Start the VM*/125 /* Start VM: */ 1808 126 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 1809 127 console.PowerUpPaused() : console.PowerUp(); … … 1812 130 if (!console.isOk()) 1813 131 { 1814 vboxProblem().cannotStartMachine (console); 1815 /* close this window (this will call closeView()) */ 1816 close(); 1817 1818 LogFlowFunc (("Error starting VM\n")); 1819 LogFlowFuncLeave(); 1820 return; 1821 } 1822 1823 mConsole->attach(); 1824 1825 /* Disable auto closure because we want to have a chance to show the 1826 * error dialog on startup failure */ 1827 mNoAutoClose = true; 1828 1829 /* show the "VM starting / restoring" progress dialog */ 1830 132 vboxProblem().cannotStartMachine(console); 133 machineWindowWrapper()->machineWindow()->close(); 134 return; 135 } 136 137 //machineWindowWrapper()->machineView()->attach(); 138 139 /* Disable auto closure because we want to have a chance to show the error dialog on startup failure: */ 140 setPreventAutoClose(true); 141 142 /* Show "Starting/Restoring" progress dialog: */ 1831 143 if (saved) 1832 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0);144 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineView(), 0); 1833 145 else 1834 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1835 146 vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineView()); 147 148 /* Check for an progress failure */ 1836 149 if (progress.GetResultCode() != 0) 1837 150 { 1838 vboxProblem().cannotStartMachine (progress); 1839 /* close this window (this will call closeView()) */ 1840 close(); 1841 1842 LogFlowFunc (("Error starting VM\n")); 1843 LogFlowFuncLeave(); 1844 return; 1845 } 1846 1847 mNoAutoClose = false; 1848 1849 /* Check if we missed a really quick termination after successful 1850 * startup, and process it if we did. */ 1851 if ( mMachineState == KMachineState_PoweredOff 1852 || mMachineState == KMachineState_Saved 1853 || mMachineState == KMachineState_Teleported 1854 || mMachineState == KMachineState_Aborted 1855 ) 1856 { 1857 close(); 1858 LogFlowFuncLeave(); 1859 return; 1860 } 1861 1862 /* Currently the machine is started and the guest API could be used... 1863 * Checking if the fullscreen mode should be activated */ 151 vboxProblem().cannotStartMachine(progress); 152 machineWindowWrapper()->machineWindow()->close(); 153 return; 154 } 155 156 /* Enable auto closure again: */ 157 setPreventAutoClose(false); 158 159 /* Check if we missed a really quick termination after successful startup, and process it if we did: */ 160 if (machineState() == KMachineState_PoweredOff || machineState() == KMachineState_Saved || 161 machineState() == KMachineState_Teleported || machineState() == KMachineState_Aborted) 162 { 163 machineWindowWrapper()->machineWindow()->close(); 164 return; 165 } 166 167 #if 0 // TODO: Is it necessary now? 168 * Checking if the fullscreen mode should be activated: */ 1864 169 QString str = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 1865 170 if (str == "on") … … 1867 172 1868 173 /* If seamless mode should be enabled then check if it is enabled 1869 * currently and re-enable it if seamless is supported */1870 if (mVmSeamlessAction->isChecked() && m IsSeamlessSupported && mIsGraphicsSupported)174 * currently and re-enable it if seamless is supported: */ 175 if (mVmSeamlessAction->isChecked() && m_bIsSeamlessSupported && m_bIsGraphicsSupported) 1871 176 toggleFullscreenMode (true, true); 1872 #ifdef VBOX_WITH_DEBUGGER_GUI 177 178 # ifdef VBOX_WITH_DEBUGGER_GUI 1873 179 /* Open the debugger in "full screen" mode requested by the user. */ 1874 180 else if (vboxGlobal().isDebuggerAutoShowEnabled()) … … 1882 188 1883 189 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled()) 1884 dbgShowStatistics();190 sltShowDebugStatistics(); 1885 191 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled()) 1886 dbgShowCommandLine();192 sltShowDebugCommandLine(); 1887 193 1888 194 if (!vboxGlobal().isStartPausedEnabled()) 1889 mConsole->pause (false); 1890 } 195 machineWindowWrapper()->machineView()->pause (false); 196 } 197 # endif 1891 198 #endif 1892 199 1893 mIsOpenViewFinished = true; 1894 LogFlowFuncLeave(); 200 setOpenViewFinished(true); 1895 201 1896 202 #ifdef VBOX_WITH_UPDATE_REQUEST 1897 vboxGlobal().showUpdateDialog (false /* aForce */); 203 /* Check for updates if necessary: */ 204 vboxGlobal().showUpdateDialog(false /* aForce */); 1898 205 #endif 1899 206 1900 /* Finally check the status of required features. */ 1901 checkRequiredFeatures(); 1902 1903 /* Re-request all the static values finally after 1904 * view is really opened and attached. */ 1905 updateAppearanceOf (VirtualizationStuff); 1906 } 1907 1908 /** 1909 * Helper to safely close the main console window. 1910 * 1911 * This method ensures that close() will not be called if there is some 1912 * modal widget currently being executed, as it can cause uninitialization 1913 * at the point of code where it is not expected at all (example: 1914 * VBoxConsoleView::mouseEvent() calling 1915 * VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to 1916 * close the current modal widget is done and tryClose() is rescheduled for 1917 * later execution using a single-shot zero timer. 1918 * 1919 * In particular, this method is used by updateMachineState() when the VM 1920 * goes offline, which can even happen if we are inside the modal event loop, 1921 * (for example, the VM has been externally powered off or the guest OS 1922 * has initiated a shutdown procedure). 1923 */ 1924 void VBoxConsoleWnd::tryClose() 1925 { 1926 /* First close any open modal & popup widgets. Use a single shot with 1927 * timeout 0 to allow the widgets to cleany close and test then again. If 1928 * all open widgets are closed destroy ourself. */ 1929 QWidget *widget = QApplication::activeModalWidget() ? 1930 QApplication::activeModalWidget() : 1931 QApplication::activePopupWidget() ? 1932 QApplication::activePopupWidget() : 0; 1933 if (widget) 1934 { 1935 widget->close(); 1936 QTimer::singleShot (0, this, SLOT (tryClose())); 1937 } 1938 else 1939 close(); 1940 } 1941 1942 void VBoxConsoleWnd::vmFullscreen (bool aOn) 1943 { 1944 bool ok = toggleFullscreenMode (aOn, false /* aSeamless */); 1945 if (!ok) 1946 { 1947 /* On failure, restore the previous button state */ 1948 mVmFullscreenAction->blockSignals (true); 1949 mVmFullscreenAction->setChecked (!aOn); 1950 mVmFullscreenAction->blockSignals (false); 1951 } 1952 } 1953 1954 void VBoxConsoleWnd::vmSeamless (bool aOn) 1955 { 1956 /* Check if it is possible to enter/leave seamless mode */ 1957 if ((mIsSeamlessSupported && mIsGraphicsSupported) || !aOn) 1958 { 1959 bool ok = toggleFullscreenMode (aOn, true /* aSeamless */); 1960 if (!ok) 1961 { 1962 /* On failure, restore the previous button state */ 1963 mVmSeamlessAction->blockSignals (true); 1964 mVmSeamlessAction->setChecked (!aOn); 1965 mVmSeamlessAction->blockSignals (false); 1966 } 1967 } 1968 } 1969 1970 void VBoxConsoleWnd::vmAutoresizeGuest (bool on) 1971 { 1972 if (!mConsole) 1973 return; 1974 1975 #if 0 /* TODO: Allow to setup status-bar! */ 1976 mAutoresizeLed->setState (on ? 3 : 1); 1977 #endif 1978 1979 mConsole->setAutoresizeGuest (on); 1980 } 1981 1982 void VBoxConsoleWnd::vmAdjustWindow() 1983 { 1984 if (mConsole) 1985 { 1986 if (isWindowMaximized()) 1987 showNormal(); 1988 mConsole->normalizeGeometry (true /* adjustPosition */); 1989 } 1990 } 1991 1992 void VBoxConsoleWnd::vmDisableMouseIntegration (bool aOff) 1993 { 1994 if (mConsole) 1995 { 1996 mConsole->setMouseIntegrationEnabled (!aOff); 1997 updateAppearanceOf (DisableMouseIntegrAction); 1998 } 1999 } 2000 2001 void VBoxConsoleWnd::vmTypeCAD() 2002 { 2003 if (mConsole) 2004 { 2005 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2006 Assert (!keyboard.isNull()); 2007 keyboard.PutCAD(); 2008 AssertWrapperOk (keyboard); 2009 } 2010 } 2011 2012 #ifdef Q_WS_X11 2013 void VBoxConsoleWnd::vmTypeCABS() 2014 { 2015 if (mConsole) 2016 { 2017 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2018 Assert (!keyboard.isNull()); 2019 static QVector <LONG> sSequence (6); 2020 sSequence[0] = 0x1d; // Ctrl down 2021 sSequence[1] = 0x38; // Alt down 2022 sSequence[2] = 0x0E; // Backspace down 2023 sSequence[3] = 0x8E; // Backspace up 2024 sSequence[4] = 0xb8; // Alt up 2025 sSequence[5] = 0x9d; // Ctrl up 2026 keyboard.PutScancodes (sSequence); 2027 AssertWrapperOk (keyboard); 2028 } 2029 } 2030 #endif 2031 2032 void VBoxConsoleWnd::vmTakeSnapshot() 2033 { 2034 AssertReturn (mConsole, (void) 0); 2035 2036 /* remember the paused state */ 2037 bool wasPaused = mMachineState == KMachineState_Paused; 2038 if (!wasPaused) 2039 { 2040 /* Suspend the VM and ignore the close event if failed to do so. 2041 * pause() will show the error message to the user. */ 2042 if (!mConsole->pause (true)) 2043 return; 2044 } 2045 2046 CMachine machine = mSession.GetMachine(); 2047 2048 VBoxTakeSnapshotDlg dlg (this, machine); 2049 2050 QString typeId = machine.GetOSTypeId(); 2051 dlg.mLbIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 2052 2053 /* search for the max available filter index */ 2054 QString nameTemplate = tr ("Snapshot %1"); 2055 int maxSnapshotIndex = searchMaxSnapshotIndex (machine, machine.GetSnapshot (QString()), nameTemplate); 2056 dlg.mLeName->setText (nameTemplate.arg (++ maxSnapshotIndex)); 2057 2058 if (dlg.exec() == QDialog::Accepted) 2059 { 2060 CConsole console = mSession.GetConsole(); 2061 2062 CProgress progress = console.TakeSnapshot (dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 2063 2064 if (console.isOk()) 2065 { 2066 /* Show the "Taking Snapshot" progress dialog */ 2067 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 2068 2069 if (progress.GetResultCode() != 0) 2070 vboxProblem().cannotTakeSnapshot (progress); 2071 } 2072 else 2073 vboxProblem().cannotTakeSnapshot (console); 2074 } 2075 2076 /* Restore the running state if needed */ 2077 if (!wasPaused) 2078 mConsole->pause (false); 2079 } 2080 2081 void VBoxConsoleWnd::vmShowInfoDialog() 2082 { 2083 VBoxVMInformationDlg::createInformationDlg (mSession, mConsole); 2084 } 2085 2086 void VBoxConsoleWnd::vmReset() 2087 { 2088 if (mConsole) 2089 { 2090 if (vboxProblem().confirmVMReset (this)) 2091 mConsole->console().Reset(); 2092 } 2093 } 2094 2095 void VBoxConsoleWnd::vmPause (bool aOn) 2096 { 2097 if (mConsole) 2098 { 2099 mConsole->pause (aOn); 2100 updateAppearanceOf (PauseAction); 2101 } 2102 } 2103 2104 void VBoxConsoleWnd::vmACPIShutdown() 2105 { 2106 if (!mSession.GetConsole().GetGuestEnteredACPIMode()) 2107 return vboxProblem().cannotSendACPIToMachine(); 2108 2109 if (mConsole) 2110 { 2111 CConsole console = mConsole->console(); 2112 console.PowerButton(); 2113 if (!console.isOk()) 2114 vboxProblem().cannotACPIShutdownMachine (console); 2115 } 2116 } 2117 2118 void VBoxConsoleWnd::vmClose() 2119 { 2120 if (mConsole) 2121 close(); 2122 } 2123 2124 void VBoxConsoleWnd::devicesSwitchVrdp (bool aOn) 2125 { 2126 if (!mConsole) return; 2127 2128 CVRDPServer vrdpServer = mSession.GetMachine().GetVRDPServer(); 2129 /* This method should not be executed if vrdpServer is null */ 2130 Assert (!vrdpServer.isNull()); 2131 2132 vrdpServer.SetEnabled (aOn); 2133 updateAppearanceOf (VRDPStuff); 2134 } 2135 2136 void VBoxConsoleWnd::devicesOpenNetworkDialog() 2137 { 2138 if (!mConsole) return; 2139 2140 VBoxNetworkDialog dlg (mConsole, mSession); 2141 dlg.exec(); 2142 } 2143 2144 void VBoxConsoleWnd::devicesOpenSFDialog() 2145 { 2146 if (!mConsole) return; 2147 2148 VBoxSFDialog dlg (mConsole, mSession); 2149 dlg.exec(); 2150 } 2151 2152 void VBoxConsoleWnd::devicesInstallGuestAdditions() 2153 { 2154 char szAppPrivPath [RTPATH_MAX]; 2155 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); 2156 AssertRC (rc); 2157 2158 QString src1 = QString (szAppPrivPath) + "/VBoxGuestAdditions.iso"; 2159 QString src2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 2160 2161 /* Check the standard image locations */ 2162 if (QFile::exists (src1)) 2163 return installGuestAdditionsFrom (src1); 2164 else if (QFile::exists (src2)) 2165 return installGuestAdditionsFrom (src2); 2166 2167 /* Check for the already registered image */ 2168 CVirtualBox vbox = vboxGlobal().virtualBox(); 2169 QString name = QString ("VBoxGuestAdditions_%1.iso").arg (vbox.GetVersion().remove ("_OSE")); 2170 2171 CMediumVector vec = vbox.GetDVDImages(); 2172 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 2173 { 2174 QString path = it->GetLocation(); 2175 /* Compare the name part ignoring the file case */ 2176 QString fn = QFileInfo (path).fileName(); 2177 if (RTPathCompare (name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 2178 return installGuestAdditionsFrom (path); 2179 } 2180 2181 /* Download the required image */ 2182 int result = vboxProblem().cannotFindGuestAdditions ( 2183 QDir::toNativeSeparators (src1), QDir::toNativeSeparators (src2)); 2184 if (result == QIMessageBox::Yes) 2185 { 2186 QString source = QString ("http://download.virtualbox.org/virtualbox/%1/") 2187 .arg (vbox.GetVersion().remove ("_OSE")) + name; 2188 QString target = QDir (vboxGlobal().virtualBox().GetHomeFolder()) 2189 .absoluteFilePath (name); 2190 2191 VBoxAdditionsDownloader *dl = 2192 new VBoxAdditionsDownloader (source, target, mDevicesInstallGuestToolsAction); 2193 statusBar()->addWidget (dl, 0); 2194 dl->start(); 2195 } 2196 } 2197 2198 void VBoxConsoleWnd::prepareStorageMenu() 2199 { 2200 QMenu *menu = qobject_cast <QMenu*> (sender()); 2201 Assert (menu); 2202 menu->clear(); 2203 2204 KDeviceType deviceType = menu == mDevicesCDMenu ? KDeviceType_DVD : 2205 menu == mDevicesFDMenu ? KDeviceType_Floppy : 2206 KDeviceType_Null; 2207 Assert (deviceType != KDeviceType_Null); 2208 2209 VBoxDefs::MediumType mediumType = menu == mDevicesCDMenu ? VBoxDefs::MediumType_DVD : 2210 menu == mDevicesFDMenu ? VBoxDefs::MediumType_Floppy : 2211 VBoxDefs::MediumType_Invalid; 2212 Assert (mediumType != VBoxDefs::MediumType_Invalid); 2213 2214 CMachine machine = mSession.GetMachine(); 2215 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 2216 foreach (const CMediumAttachment &attachment, attachments) 2217 { 2218 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 2219 if ( !controller.isNull() 2220 && (attachment.GetType() == deviceType)) 2221 { 2222 /* Attachment menu item */ 2223 QMenu *attachmentMenu = 0; 2224 if (menu->menuAction()->data().toInt() > 1) 2225 { 2226 attachmentMenu = new QMenu (menu); 2227 attachmentMenu->setTitle (QString ("%1 (%2)").arg (controller.GetName()) 2228 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), 2229 attachment.GetPort(), 2230 attachment.GetDevice())))); 2231 switch (controller.GetBus()) 2232 { 2233 case KStorageBus_IDE: 2234 attachmentMenu->setIcon (QIcon (":/ide_16px.png")); break; 2235 case KStorageBus_SATA: 2236 attachmentMenu->setIcon (QIcon (":/sata_16px.png")); break; 2237 case KStorageBus_SCSI: 2238 attachmentMenu->setIcon (QIcon (":/scsi_16px.png")); break; 2239 case KStorageBus_Floppy: 2240 attachmentMenu->setIcon (QIcon (":/floppy_16px.png")); break; 2241 default: 2242 break; 2243 } 2244 menu->addMenu (attachmentMenu); 2245 } 2246 else attachmentMenu = menu; 2247 2248 /* Mount Medium actions */ 2249 CMediumVector mediums; 2250 switch (mediumType) 2251 { 2252 case VBoxDefs::MediumType_DVD: 2253 mediums += vboxGlobal().virtualBox().GetHost().GetDVDDrives(); 2254 mediums += vboxGlobal().virtualBox().GetDVDImages(); 2255 break; 2256 case VBoxDefs::MediumType_Floppy: 2257 mediums += vboxGlobal().virtualBox().GetHost().GetFloppyDrives(); 2258 mediums += vboxGlobal().virtualBox().GetFloppyImages(); 2259 break; 2260 default: 2261 break; 2262 } 2263 2264 int mediumsToBeShown = 0; 2265 const int maxMediumsToBeShown = 5; 2266 CMedium currentMedium = attachment.GetMedium(); 2267 QString currentId = currentMedium.isNull() ? QString::null : currentMedium.GetId(); 2268 bool currentUsed = false; 2269 foreach (CMedium medium, mediums) 2270 { 2271 bool isMediumUsed = false; 2272 foreach (const CMediumAttachment &otherAttachment, attachments) 2273 { 2274 if (otherAttachment != attachment) 2275 { 2276 CMedium otherMedium = otherAttachment.GetMedium(); 2277 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 2278 { 2279 isMediumUsed = true; 2280 break; 2281 } 2282 } 2283 } 2284 if (!isMediumUsed) 2285 { 2286 if (!currentUsed && !currentMedium.isNull() && mediumsToBeShown == maxMediumsToBeShown - 1) 2287 medium = currentMedium; 2288 2289 if (medium.GetId() == currentId) 2290 currentUsed = true; 2291 2292 QAction *mountMediumAction = new QAction (VBoxMedium (medium, mediumType).name(), attachmentMenu); 2293 mountMediumAction->setCheckable (true); 2294 mountMediumAction->setChecked (!currentMedium.isNull() && medium.GetId() == currentId); 2295 mountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2296 attachment.GetPort(), 2297 attachment.GetDevice(), 2298 medium.GetId()))); 2299 connect (mountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2300 attachmentMenu->addAction (mountMediumAction); 2301 ++ mediumsToBeShown; 2302 if (mediumsToBeShown == maxMediumsToBeShown) 2303 break; 2304 } 2305 } 2306 2307 /* Virtual Media Manager action */ 2308 QAction *callVMMAction = new QAction (attachmentMenu); 2309 callVMMAction->setIcon (QIcon (":/diskimage_16px.png")); 2310 callVMMAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2311 attachment.GetPort(), 2312 attachment.GetDevice(), 2313 mediumType))); 2314 connect (callVMMAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2315 attachmentMenu->addAction (callVMMAction); 2316 2317 /* Separator */ 2318 attachmentMenu->addSeparator(); 2319 2320 /* Unmount Medium action */ 2321 QAction *unmountMediumAction = new QAction (attachmentMenu); 2322 unmountMediumAction->setEnabled (!currentMedium.isNull()); 2323 unmountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2324 attachment.GetPort(), 2325 attachment.GetDevice()))); 2326 connect (unmountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2327 attachmentMenu->addAction (unmountMediumAction); 2328 2329 /* Switch CD/FD naming */ 2330 switch (mediumType) 2331 { 2332 case VBoxDefs::MediumType_DVD: 2333 callVMMAction->setText (tr ("More CD/DVD Images...")); 2334 unmountMediumAction->setText (tr ("Unmount CD/DVD Device")); 2335 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/cd_unmount_16px.png", 2336 ":/cd_unmount_dis_16px.png")); 2337 break; 2338 case VBoxDefs::MediumType_Floppy: 2339 callVMMAction->setText (tr ("More Floppy Images...")); 2340 unmountMediumAction->setText (tr ("Unmount Floppy Device")); 2341 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/fd_unmount_16px.png", 2342 ":/fd_unmount_dis_16px.png")); 2343 break; 2344 default: 2345 break; 2346 } 2347 } 2348 } 2349 2350 if (menu->menuAction()->data().toInt() == 0) 2351 { 2352 /* Empty menu item */ 2353 Assert (menu->isEmpty()); 2354 QAction *emptyMenuAction = new QAction (menu); 2355 emptyMenuAction->setEnabled (false); 2356 switch (mediumType) 2357 { 2358 case VBoxDefs::MediumType_DVD: 2359 emptyMenuAction->setText (tr ("No CD/DVD Devices Attached")); 2360 break; 2361 case VBoxDefs::MediumType_Floppy: 2362 emptyMenuAction->setText (tr ("No Floppy Devices Attached")); 2363 break; 2364 default: 2365 break; 2366 } 2367 emptyMenuAction->setIcon (VBoxGlobal::iconSet (":/delete_16px.png", ":/delete_dis_16px.png")); 2368 menu->addAction (emptyMenuAction); 2369 } 2370 } 2371 2372 void VBoxConsoleWnd::prepareNetworkMenu() 2373 { 2374 mDevicesNetworkMenu->clear(); 2375 mDevicesNetworkMenu->addAction (mDevicesNetworkDialogAction); 2376 } 2377 2378 void VBoxConsoleWnd::prepareSFMenu() 2379 { 2380 mDevicesSFMenu->clear(); 2381 mDevicesSFMenu->addAction (mDevicesSFDialogAction); 2382 } 2383 2384 void VBoxConsoleWnd::mountMedium() 2385 { 2386 /* Get sender action */ 2387 QAction *action = qobject_cast <QAction*> (sender()); 2388 Assert (action); 2389 2390 /* Get current machine */ 2391 CMachine machine = mSession.GetMachine(); 2392 2393 /* Get mount-target */ 2394 MountTarget target = action->data().value <MountTarget>(); 2395 2396 /* Current mount-target attributes */ 2397 CMediumAttachment currentAttachment = machine.GetMediumAttachment (target.name, target.port, target.device); 2398 CMedium currentMedium = currentAttachment.GetMedium(); 2399 QString currentId = currentMedium.isNull() ? QString ("") : currentMedium.GetId(); 2400 2401 /* New mount-target attributes */ 2402 QString newId = QString (""); 2403 bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid; 2404 2405 /* Open Virtual Media Manager to select image id */ 2406 if (selectWithMediaManager) 2407 { 2408 /* Search for already used images */ 2409 QStringList usedImages; 2410 foreach (const CMediumAttachment &attachment, machine.GetMediumAttachments()) 2411 { 2412 CMedium medium = attachment.GetMedium(); 2413 if (attachment != currentAttachment && !medium.isNull() && !medium.GetHostDrive()) 2414 usedImages << medium.GetId(); 2415 } 2416 /* Open VMM Dialog */ 2417 VBoxMediaManagerDlg dlg (this); 2418 dlg.setup (target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages); 2419 if (dlg.exec() == QDialog::Accepted) 2420 newId = dlg.selectedId(); 2421 else return; 2422 } 2423 /* Use medium which was sent */ 2424 else if (!target.id.isNull() && target.id != currentId) 2425 newId = target.id; 2426 2427 bool mount = !newId.isEmpty(); 2428 2429 /* Remount medium to the predefined port/device */ 2430 bool wasMounted = false; 2431 machine.MountMedium (target.name, target.port, target.device, newId, false /* force */); 2432 if (machine.isOk()) 2433 wasMounted = true; 2434 else 2435 { 2436 /* Ask for force remounting */ 2437 if (vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok) 2438 { 2439 /* Force remount medium to the predefined port/device. */ 2440 machine.MountMedium (target.name, target.port, target.device, newId, true /* force */); 2441 if (machine.isOk()) 2442 wasMounted = true; 2443 else 2444 vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */); 2445 } 2446 } 2447 2448 /* Save medium mounted at runtime */ 2449 if (wasMounted && mIsAutoSaveMedia) 2450 { 2451 machine.SaveSettings(); 2452 if (!machine.isOk()) 2453 vboxProblem().cannotSaveMachineSettings (machine); 2454 } 2455 } 2456 2457 /** 2458 * Attach/Detach selected USB Device. 2459 */ 2460 void VBoxConsoleWnd::switchUSB (QAction *aAction) 2461 { 2462 if (!mConsole) return; 2463 2464 CConsole console = mSession.GetConsole(); 2465 AssertWrapperOk (mSession); 2466 2467 CUSBDevice usb = mDevicesUSBMenu->getUSB (aAction); 2468 /* if null then some other item but a USB device is selected */ 2469 if (usb.isNull()) 2470 return; 2471 2472 if (!aAction->isChecked()) 2473 { 2474 console.DetachUSBDevice (usb.GetId()); 2475 if (!console.isOk()) 2476 { 2477 /// @todo (r=dmik) the dialog should be either modeless 2478 // or we have to pause the VM 2479 vboxProblem().cannotDetachUSBDevice (console, vboxGlobal().details (usb)); 2480 } 2481 } 2482 else 2483 { 2484 console.AttachUSBDevice (usb.GetId()); 2485 if (!console.isOk()) 2486 { 2487 /// @todo (r=dmik) the dialog should be either modeless 2488 // or we have to pause the VM 2489 vboxProblem().cannotAttachUSBDevice (console, vboxGlobal().details (usb)); 2490 } 2491 } 2492 } 2493 2494 void VBoxConsoleWnd::showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent) 2495 { 2496 if (aInd == mCDLed) 2497 { 2498 mDevicesCDMenu->exec (aEvent->globalPos()); 2499 } 2500 #if 0 /* TODO: Allow to setup status-bar! */ 2501 else if (aInd == mFDLed) 2502 { 2503 mDevicesFDMenu->exec (aEvent->globalPos()); 2504 } 2505 #endif 2506 else if (aInd == mNetLed) 2507 { 2508 if (mDevicesNetworkMenu->isEnabled()) 2509 mDevicesNetworkMenu->exec (aEvent->globalPos()); 2510 } 2511 else if (aInd == mUSBLed) 2512 { 2513 if (mDevicesUSBMenu->isEnabled()) 2514 mDevicesUSBMenu->exec (aEvent->globalPos()); 2515 } 2516 else if (aInd == mSFLed) 2517 { 2518 if (mDevicesSFMenu->isEnabled()) 2519 mDevicesSFMenu->exec (aEvent->globalPos()); 2520 } 2521 else if (aInd == mMouseLed) 2522 { 2523 mVmDisMouseIntegrMenu->exec (aEvent->globalPos()); 2524 } 2525 #if 0 /* TODO: Allow to setup status-bar! */ 2526 else if (aInd == mVrdpLed) 2527 { 2528 mDevicesVRDPMenu->exec (aEvent->globalPos()); 2529 } 2530 else if (aInd == mAutoresizeLed) 2531 { 2532 mVmAutoresizeMenu->exec (aEvent->globalPos()); 2533 } 2534 #endif 2535 } 2536 2537 void VBoxConsoleWnd::updateDeviceLights() 2538 { 2539 if (mConsole) 2540 { 2541 CConsole &console = mConsole->console(); 2542 int st; 2543 if (mHDLed->state() != KDeviceActivity_Null) 2544 { 2545 st = console.GetDeviceActivity (KDeviceType_HardDisk); 2546 if (mHDLed->state() != st) 2547 mHDLed->setState (st); 2548 } 2549 if (mCDLed->state() != KDeviceActivity_Null) 2550 { 2551 st = console.GetDeviceActivity (KDeviceType_DVD); 2552 if (mCDLed->state() != st) 2553 mCDLed->setState (st); 2554 } 2555 #if 0 /* TODO: Allow to setup status-bar! */ 2556 if (mFDLed->state() != KDeviceActivity_Null) 2557 { 2558 st = console.GetDeviceActivity (KDeviceType_Floppy); 2559 if (mFDLed->state() != st) 2560 mFDLed->setState (st); 2561 } 2562 #endif 2563 if (mNetLed->state() != KDeviceActivity_Null) 2564 { 2565 st = console.GetDeviceActivity (KDeviceType_Network); 2566 if (mNetLed->state() != st) 2567 mNetLed->setState (st); 2568 } 2569 if (mUSBLed->state() != KDeviceActivity_Null) 2570 { 2571 st = console.GetDeviceActivity (KDeviceType_USB); 2572 if (mUSBLed->state() != st) 2573 mUSBLed->setState (st); 2574 } 2575 if (mSFLed->state() != KDeviceActivity_Null) 2576 { 2577 st = console.GetDeviceActivity (KDeviceType_SharedFolder); 2578 if (mSFLed->state() != st) 2579 mSFLed->setState (st); 2580 } 2581 } 2582 } 2583 2584 void VBoxConsoleWnd::updateMachineState (KMachineState aState) 2585 { 2586 bool guruMeditation = false; 2587 2588 if (mConsole && mMachineState != aState) 2589 { 2590 switch (aState) 2591 { 2592 case KMachineState_Stuck: 2593 { 2594 guruMeditation = true; 2595 break; 2596 } 2597 case KMachineState_Paused: 2598 { 2599 if (!mVmPauseAction->isChecked()) 2600 mVmPauseAction->setChecked (true); 2601 break; 2602 } 2603 case KMachineState_Running: 2604 case KMachineState_Teleporting: /** @todo Live Migration: Check out this. */ 2605 case KMachineState_LiveSnapshotting: 2606 { 2607 if ( ( mMachineState == KMachineState_Paused 2608 || mMachineState == KMachineState_TeleportingPausedVM) 2609 && mVmPauseAction->isChecked() 2610 ) 2611 mVmPauseAction->setChecked (false); 2612 break; 2613 } 2614 #ifdef Q_WS_X11 2615 case KMachineState_Starting: 2616 case KMachineState_Restoring: 2617 case KMachineState_TeleportingIn: 2618 { 2619 /* The keyboard handler may wish to do some release logging 2620 on startup. Tell it that the logger is now active. */ 2621 doXKeyboardLogging (QX11Info::display()); 2622 break; 2623 } 2624 #endif 2625 default: 2626 break; 2627 } 2628 2629 bool isRunningOrPaused = aState == KMachineState_Running 2630 || aState == KMachineState_Teleporting 2631 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2632 || aState == KMachineState_Paused; 2633 2634 /* Enable/Disable actions that are not managed by updateAppearanceOf() */ 2635 2636 mRunningActions->setEnabled ( aState == KMachineState_Running 2637 || aState == KMachineState_Teleporting 2638 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2639 ); 2640 mRunningOrPausedActions->setEnabled (isRunningOrPaused); 2641 2642 mMachineState = aState; 2643 2644 updateAppearanceOf (Caption | 2645 HardDiskStuff | DVDStuff | FloppyStuff | 2646 NetworkStuff | USBStuff | VRDPStuff | 2647 PauseAction | DisableMouseIntegrAction); 2648 2649 if ( aState == KMachineState_PoweredOff 2650 || aState == KMachineState_Saved 2651 || aState == KMachineState_Teleported 2652 || aState == KMachineState_Aborted 2653 ) 2654 { 2655 /* VM has been powered off or saved or aborted, no matter 2656 * internally or externally -- we must *safely* close the console 2657 * window unless auto closure is disabled. */ 2658 if (!mNoAutoClose) 2659 tryClose(); 2660 } 2661 } 2662 2663 if (guruMeditation) 2664 { 2665 mConsole->setIgnoreGuestResize (true); 2666 2667 CConsole console = mConsole->console(); 2668 QString logFolder = console.GetMachine().GetLogFolder(); 2669 2670 /* Take the screenshot for debugging purposes and save it */ 2671 QString fname = logFolder + "/VBox.png"; 2672 2673 CDisplay dsp = console.GetDisplay(); 2674 QImage shot = QImage (dsp.GetWidth(), dsp.GetHeight(), QImage::Format_RGB32); 2675 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 2676 shot.save (QFile::encodeName (fname), "PNG"); 2677 2678 if (vboxProblem().remindAboutGuruMeditation (console, QDir::toNativeSeparators (logFolder))) 2679 { 2680 qApp->processEvents(); 2681 console.PowerDown(); 2682 if (!console.isOk()) 2683 vboxProblem().cannotStopMachine (console); 2684 } 2685 } 2686 2687 #ifdef Q_WS_MAC 2688 if (mConsole) 2689 mConsole->updateDockOverlay(); 2690 #endif 2691 } 2692 2693 void VBoxConsoleWnd::updateMouseState (int aState) 2694 { 2695 mVmDisableMouseIntegrAction->setEnabled (aState & VBoxConsoleView::MouseAbsolute); 2696 2697 if ((aState & VBoxConsoleView::MouseAbsoluteDisabled) && 2698 (aState & VBoxConsoleView::MouseAbsolute) && 2699 !(aState & VBoxConsoleView::MouseCaptured)) 2700 { 2701 mMouseLed->setState (4); 2702 } 2703 else 2704 { 2705 mMouseLed->setState (aState & (VBoxConsoleView::MouseAbsolute | VBoxConsoleView::MouseCaptured)); 2706 } 2707 } 2708 2709 void VBoxConsoleWnd::updateAdditionsState (const QString &aVersion, 2710 bool aActive, 2711 bool aSeamlessSupported, 2712 bool aGraphicsSupported) 2713 { 2714 mVmAutoresizeGuestAction->setEnabled (aActive && aGraphicsSupported); 2715 if ((mIsSeamlessSupported != aSeamlessSupported) || 2716 (mIsGraphicsSupported != aGraphicsSupported)) 2717 { 2718 mVmSeamlessAction->setEnabled (aSeamlessSupported && aGraphicsSupported); 2719 mIsSeamlessSupported = aSeamlessSupported; 2720 mIsGraphicsSupported = aGraphicsSupported; 2721 /* If seamless mode should be enabled then check if it is enabled 2722 * currently and re-enable it if open-view procedure is finished */ 2723 if (mVmSeamlessAction->isChecked() && mIsOpenViewFinished && aSeamlessSupported && aGraphicsSupported) 2724 toggleFullscreenMode (true, true); 2725 /* Disable auto-resizing if advanced graphics are not available */ 2726 mConsole->setAutoresizeGuest (mIsGraphicsSupported && mVmAutoresizeGuestAction->isChecked()); 2727 mVmAutoresizeGuestAction->setEnabled (mIsGraphicsSupported); 2728 } 2729 2730 /* Check the GA version only in case of additions are active */ 2731 if (!aActive) 2732 return; 2733 2734 /* Check the Guest Additions version and warn the user about possible 2735 * compatibility issues in case if the installed version is outdated. */ 2736 uint version = aVersion.toUInt(); 2737 QString versionStr = QString ("%1.%2") 2738 .arg (RT_HIWORD (version)).arg (RT_LOWORD (version)); 2739 QString expectedStr = QString ("%1.%2") 2740 .arg (VMMDEV_VERSION_MAJOR).arg (VMMDEV_VERSION_MINOR); /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 2741 2742 if (RT_HIWORD (version) < VMMDEV_VERSION_MAJOR) 2743 { 2744 vboxProblem().warnAboutTooOldAdditions (this, versionStr, expectedStr); 2745 } 2746 else if (RT_HIWORD (version) == VMMDEV_VERSION_MAJOR && 2747 RT_LOWORD (version) < VMMDEV_VERSION_MINOR) 2748 { 2749 vboxProblem().warnAboutOldAdditions (this, versionStr, expectedStr); 2750 } 2751 else if (version > VMMDEV_VERSION) 2752 { 2753 vboxProblem().warnAboutNewAdditions (this, versionStr, expectedStr); 2754 } 2755 } 2756 2757 void VBoxConsoleWnd::updateNetworkAdaptersState() 2758 { 2759 updateAppearanceOf (NetworkStuff); 2760 } 2761 2762 void VBoxConsoleWnd::updateUsbState() 2763 { 2764 updateAppearanceOf (USBStuff); 2765 } 2766 2767 void VBoxConsoleWnd::updateMediaDriveState (VBoxDefs::MediumType aType) 2768 { 2769 Assert (aType == VBoxDefs::MediumType_DVD || aType == VBoxDefs::MediumType_Floppy); 2770 updateAppearanceOf (aType == VBoxDefs::MediumType_DVD ? DVDStuff : 2771 aType == VBoxDefs::MediumType_Floppy ? FloppyStuff : 2772 AllStuff); 2773 } 2774 2775 void VBoxConsoleWnd::updateSharedFoldersState() 2776 { 2777 updateAppearanceOf (SharedFolderStuff); 2778 } 2779 2780 /** 2781 * This slot is called just after leaving the fullscreen/seamless mode, 2782 * when the console was resized to previous size. 2783 */ 2784 void VBoxConsoleWnd::onExitFullscreen() 2785 { 2786 mConsole->setIgnoreMainwndResize (false); 2787 } 2788 2789 void VBoxConsoleWnd::unlockActionsSwitch() 2790 { 2791 if (mIsSeamless) 2792 mVmSeamlessAction->setEnabled (true); 2793 else if (mIsFullscreen) 2794 mVmFullscreenAction->setEnabled (true); 2795 else 2796 { 2797 mVmSeamlessAction->setEnabled (mIsSeamlessSupported && mIsGraphicsSupported); 2798 mVmFullscreenAction->setEnabled (true); 2799 } 2800 2801 #ifdef Q_WS_MAC 2802 if (!mIsSeamless) 2803 { 2804 /* Fade back to the normal gamma */ 2805 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 2806 CGReleaseDisplayFadeReservation (mFadeToken); 2807 } 2808 mConsole->setMouseCoalescingEnabled (true); 2809 #endif 2810 2811 #ifdef Q_WS_X11 2812 if (vboxGlobal().isKWinManaged() && !mIsSeamless && !mIsFullscreen) 2813 { 2814 /* Workaround for a KWin bug to let console window to exit 2815 * seamless mode correctly. */ 2816 setWindowFlags(Qt::Window); 2817 setVisible(true); 2818 } 2819 #endif 2820 } 2821 2822 void VBoxConsoleWnd::mtExitMode() 2823 { 2824 if (mIsSeamless) 2825 mVmSeamlessAction->toggle(); 2826 else 2827 mVmFullscreenAction->toggle(); 2828 } 2829 2830 void VBoxConsoleWnd::mtCloseVM() 2831 { 2832 mVmCloseAction->trigger(); 2833 } 2834 2835 void VBoxConsoleWnd::mtMaskUpdate() 2836 { 2837 if (mIsSeamless) 2838 setMask (mConsole->lastVisibleRegion()); 2839 } 2840 2841 void VBoxConsoleWnd::changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent) 2842 { 2843 #ifdef Q_WS_MAC 2844 if (mConsole) 2845 { 2846 mConsole->setDockIconEnabled (aEvent.mChanged); 2847 mConsole->updateDockOverlay(); 2848 } 2849 #else 2850 Q_UNUSED (aEvent); 2851 #endif 2852 } 2853 2854 void VBoxConsoleWnd::changePresentationMode (const VBoxChangePresentationModeEvent &aEvent) 2855 { 2856 Q_UNUSED (aEvent); 2857 #ifdef Q_WS_MAC 2858 # ifdef QT_MAC_USE_COCOA 2859 if (mIsFullscreen) 2860 { 2861 /* First check if we are on the primary screen, only than the 2862 presentation mode have to be changed. */ 2863 QDesktopWidget* pDesktop = QApplication::desktop(); 2864 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 2865 { 2866 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_PresentationModeEnabled).toLower(); 2867 /* Default to false if it is an empty value */ 2868 if (testStr.isEmpty() || testStr == "false") 2869 SetSystemUIMode (kUIModeAllHidden, 0); 2870 else 2871 SetSystemUIMode (kUIModeAllSuppressed, 0); 2872 } 2873 } 2874 else 2875 SetSystemUIMode (kUIModeNormal, 0); 2876 # endif /* QT_MAC_USE_COCOA */ 2877 #endif 2878 } 2879 2880 /** 2881 * Called (on non-UI thread!) when a global GUI setting changes. 2882 */ 2883 void VBoxConsoleWnd::processGlobalSettingChange (const char * /* aPublicName */, const char * /* aName */) 2884 { 2885 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 2886 } 2887 2888 /** 2889 * This function checks the status of required features and 2890 * makes a warning and/or some action if something necessary 2891 * is not in good condition. 2892 * Does nothing if no console view was opened. 2893 */ 2894 void VBoxConsoleWnd::checkRequiredFeatures() 2895 { 2896 if (!mConsole) return; 2897 2898 CConsole console = mConsole->console(); 2899 2900 /* Check if the virtualization feature is required. */ 2901 bool is64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType ( 2902 console.GetGuest().GetOSTypeId()).GetIs64Bit(); 2903 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType ( 2904 console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 2905 Assert(!is64BitsGuest || fRecommendVirtEx); 2906 bool isVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 2907 if (fRecommendVirtEx && !isVirtEnabled) 2908 { 2909 bool ret; 2910 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost() 2911 .GetProcessorFeature (KProcessorFeature_HWVirtEx); 2912 2913 vmPause (true); 2914 2915 if (is64BitsGuest) 2916 ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported); 2917 else 2918 ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported); 2919 2920 if (ret == true) 2921 close(); 2922 else 2923 vmPause (false); 2924 } 2925 } 2926 2927 void VBoxConsoleWnd::activateUICustomizations() 2928 { 2929 VBoxGlobalSettings settings = vboxGlobal().settings(); 2930 /* Process known keys */ 2931 menuBar()->setHidden (settings.isFeatureActive ("noMenuBar")); 2932 statusBar()->setHidden (settings.isFeatureActive ("noStatusBar")); 2933 } 2934 2935 void VBoxConsoleWnd::updateAppearanceOf (int aElement) 2936 { 2937 if (!mConsole) return; 2938 2939 CMachine machine = mSession.GetMachine(); 2940 CConsole console = mConsole->console(); 2941 2942 bool isStrictRunningOrPaused = mMachineState == KMachineState_Running 2943 || mMachineState == KMachineState_Paused; 2944 bool isRunningOrPaused = isStrictRunningOrPaused 2945 || mMachineState == KMachineState_Teleporting 2946 || mMachineState == KMachineState_LiveSnapshotting; 2947 2948 if (aElement & Caption) 2949 { 2950 QString snapshotName; 2951 if (machine.GetSnapshotCount() > 0) 2952 { 2953 CSnapshot snapshot = machine.GetCurrentSnapshot(); 2954 snapshotName = " (" + snapshot.GetName() + ")"; 2955 } 2956 setWindowTitle (machine.GetName() + snapshotName + 2957 " [" + vboxGlobal().toString (mMachineState) + "] - " + 2958 mCaptionPrefix); 2959 mMiniToolBar->setDisplayText (machine.GetName() + snapshotName); 2960 } 2961 if (aElement & HardDiskStuff) 2962 { 2963 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2964 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 2965 QString data; 2966 bool attachmentsPresent = false; 2967 2968 CStorageControllerVector controllers = machine.GetStorageControllers(); 2969 foreach (const CStorageController &controller, controllers) 2970 { 2971 QString attData; 2972 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 2973 foreach (const CMediumAttachment &attachment, attachments) 2974 { 2975 if (attachment.GetType() != KDeviceType_HardDisk) 2976 continue; 2977 attData += QString ("<br> <nobr>%1: %2</nobr>") 2978 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 2979 .arg (VBoxMedium (attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 2980 attachmentsPresent = true; 2981 } 2982 if (!attData.isNull()) 2983 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 2984 } 2985 2986 if (!attachmentsPresent) 2987 data += tr ("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 2988 2989 mHDLed->setToolTip (tip.arg (data)); 2990 mHDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 2991 } 2992 if (aElement & DVDStuff) 2993 { 2994 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2995 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 2996 QString data; 2997 bool attachmentsPresent = false; 2998 2999 CStorageControllerVector controllers = machine.GetStorageControllers(); 3000 foreach (const CStorageController &controller, controllers) 3001 { 3002 QString attData; 3003 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3004 foreach (const CMediumAttachment &attachment, attachments) 3005 { 3006 if (attachment.GetType() != KDeviceType_DVD) 3007 continue; 3008 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_DVD); 3009 attData += QString ("<br> <nobr>%1: %2</nobr>") 3010 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3011 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3012 if (!vboxMedium.isNull()) 3013 attachmentsPresent = true; 3014 } 3015 if (!attData.isNull()) 3016 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3017 } 3018 3019 if (data.isNull()) 3020 data = tr ("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 3021 3022 mCDLed->setToolTip (tip.arg (data)); 3023 mCDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3024 } 3025 #if 0 /* TODO: Allow to setup status-bar! */ 3026 if (aElement & FloppyStuff) 3027 { 3028 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 3029 "of the floppy devices:</nobr>%1</p>", "FD tooltip"); 3030 QString data; 3031 bool attachmentsPresent = false; 3032 3033 CStorageControllerVector controllers = machine.GetStorageControllers(); 3034 foreach (const CStorageController &controller, controllers) 3035 { 3036 QString attData; 3037 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3038 foreach (const CMediumAttachment &attachment, attachments) 3039 { 3040 if (attachment.GetType() != KDeviceType_Floppy) 3041 continue; 3042 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_Floppy); 3043 attData += QString ("<br> <nobr>%1: %2</nobr>") 3044 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3045 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3046 if (!vboxMedium.isNull()) 3047 attachmentsPresent = true; 3048 } 3049 if (!attData.isNull()) 3050 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3051 } 3052 3053 if (data.isNull()) 3054 data = tr ("<br><nobr><b>No floppy devices attached</b></nobr>", "FD tooltip"); 3055 3056 mFDLed->setToolTip (tip.arg (data)); 3057 mFDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3058 } 3059 #endif 3060 if (aElement & NetworkStuff) 3061 { 3062 ulong maxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 3063 ulong count = 0; 3064 for (ulong slot = 0; slot < maxCount; ++ slot) 3065 if (machine.GetNetworkAdapter (slot).GetEnabled()) 3066 ++ count; 3067 mNetLed->setState (count > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 3068 3069 mDevicesNetworkDialogAction->setEnabled (isStrictRunningOrPaused && count > 0); 3070 mDevicesNetworkMenu->setEnabled (isStrictRunningOrPaused && count > 0); 3071 3072 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of the " 3073 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 3074 QString info; 3075 3076 for (ulong slot = 0; slot < maxCount; ++ slot) 3077 { 3078 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot); 3079 if (adapter.GetEnabled()) 3080 info += tr ("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 3081 .arg (slot + 1) 3082 .arg (vboxGlobal().toString (adapter.GetAttachmentType())) 3083 .arg (adapter.GetCableConnected() ? 3084 tr ("connected", "Network adapters tooltip") : 3085 tr ("disconnected", "Network adapters tooltip")); 3086 } 3087 3088 if (info.isNull()) 3089 info = tr ("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 3090 3091 mNetLed->setToolTip (tip.arg (info)); 3092 } 3093 if (aElement & USBStuff) 3094 { 3095 if (!mUSBLed->isHidden()) 3096 { 3097 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3098 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 3099 QString info; 3100 3101 CUSBController usbctl = machine.GetUSBController(); 3102 if (!usbctl.isNull() && usbctl.GetEnabled()) 3103 { 3104 mDevicesUSBMenu->setEnabled (isStrictRunningOrPaused); 3105 3106 CUSBDeviceVector devsvec = console.GetUSBDevices(); 3107 for (int i = 0; i < devsvec.size(); ++ i) 3108 { 3109 CUSBDevice usb = devsvec [i]; 3110 info += QString ("<br><b><nobr>%1</nobr></b>").arg (vboxGlobal().details (usb)); 3111 } 3112 if (info.isNull()) 3113 info = tr ("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 3114 } 3115 else 3116 { 3117 mDevicesUSBMenu->setEnabled (false); 3118 info = tr ("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 3119 } 3120 3121 mUSBLed->setToolTip (tip.arg (info)); 3122 } 3123 } 3124 if (aElement & VRDPStuff) 3125 { 3126 CVRDPServer vrdpsrv = mSession.GetMachine().GetVRDPServer(); 3127 if (!vrdpsrv.isNull()) 3128 { 3129 /* update menu&status icon state */ 3130 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 3131 mDevicesSwitchVrdpAction->setChecked (isVRDPEnabled); 3132 #if 0 /* TODO: Allow to setup status-bar! */ 3133 mVrdpLed->setState (isVRDPEnabled ? 1 : 0); 3134 3135 QString tip = tr ("Indicates whether the Remote Display (VRDP Server) " 3136 "is enabled (<img src=:/vrdp_16px.png/>) or not " 3137 "(<img src=:/vrdp_disabled_16px.png/>)."); 3138 if (vrdpsrv.GetEnabled()) 3139 tip += tr ("<hr>The VRDP Server is listening on port %1").arg (vrdpsrv.GetPort()); 3140 mVrdpLed->setToolTip (tip); 3141 #endif 3142 } 3143 } 3144 if (aElement & SharedFolderStuff) 3145 { 3146 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3147 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 3148 3149 QString data; 3150 QMap <QString, QString> sfs; 3151 3152 mDevicesSFMenu->setEnabled (true); 3153 3154 /* Permanent folders */ 3155 CSharedFolderVector psfvec = machine.GetSharedFolders(); 3156 3157 for (int i = 0; i < psfvec.size(); ++ i) 3158 { 3159 CSharedFolder sf = psfvec [i]; 3160 sfs.insert (sf.GetName(), sf.GetHostPath()); 3161 } 3162 3163 /* Transient folders */ 3164 CSharedFolderVector tsfvec = console.GetSharedFolders(); 3165 3166 for (int i = 0; i < tsfvec.size(); ++ i) 3167 { 3168 CSharedFolder sf = tsfvec[i]; 3169 sfs.insert (sf.GetName(), sf.GetHostPath()); 3170 } 3171 3172 for (QMap <QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 3173 { 3174 /* Select slashes depending on the OS type */ 3175 if (VBoxGlobal::isDOSType (console.GetGuest().GetOSTypeId())) 3176 data += QString ("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 3177 .arg (it.key(), it.value()); 3178 else 3179 data += QString ("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 3180 .arg (it.key(), it.value()); 3181 } 3182 3183 if (sfs.count() == 0) 3184 data = tr ("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 3185 3186 mSFLed->setToolTip (tip.arg (data)); 3187 } 3188 if (aElement & VirtualizationStuff) 3189 { 3190 bool virtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 3191 QString virtualization = virtEnabled ? 3192 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") : 3193 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)"); 3194 3195 bool nestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 3196 QString nestedPaging = nestEnabled ? 3197 VBoxVMInformationDlg::tr ("Enabled", "nested paging") : 3198 VBoxVMInformationDlg::tr ("Disabled", "nested paging"); 3199 3200 QString tip (tr ("Indicates the status of the hardware virtualization " 3201 "features used by this virtual machine:" 3202 "<br><nobr><b>%1:</b> %2</nobr>" 3203 "<br><nobr><b>%3:</b> %4</nobr>", 3204 "Virtualization Stuff LED") 3205 .arg (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization) 3206 .arg (VBoxVMInformationDlg::tr ("Nested Paging"), nestedPaging)); 3207 3208 int cpuCount = console.GetMachine().GetCPUCount(); 3209 if (cpuCount > 1) 3210 tip += tr ("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 3211 .arg (VBoxGlobal::tr ("Processor(s)", "details report")).arg (cpuCount); 3212 3213 mVirtLed->setToolTip (tip); 3214 mVirtLed->setState (virtEnabled); 3215 } 3216 if (aElement & PauseAction) 3217 { 3218 if (!mVmPauseAction->isChecked()) 3219 { 3220 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Pause"), "P")); 3221 mVmPauseAction->setStatusTip (tr ("Suspend the execution of the virtual machine")); 3222 } 3223 else 3224 { 3225 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("R&esume"), "P")); 3226 mVmPauseAction->setStatusTip (tr ("Resume the execution of the virtual machine" ) ); 3227 } 3228 mVmPauseAction->setEnabled (isRunningOrPaused); 3229 } 3230 if (aElement & DisableMouseIntegrAction) 3231 { 3232 if (!mVmDisableMouseIntegrAction->isChecked()) 3233 { 3234 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Disable &Mouse Integration"), "I")); 3235 mVmDisableMouseIntegrAction->setStatusTip (tr ("Temporarily disable host mouse pointer integration")); 3236 } 3237 else 3238 { 3239 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Enable &Mouse Integration"), "I")); 3240 mVmDisableMouseIntegrAction->setStatusTip (tr ("Enable temporarily disabled host mouse pointer integration")); 3241 } 3242 if ( mMachineState == KMachineState_Running 3243 || mMachineState == KMachineState_Teleporting 3244 || mMachineState == KMachineState_LiveSnapshotting 3245 ) 3246 mVmDisableMouseIntegrAction->setEnabled (mConsole->isMouseAbsolute()); 3247 else 3248 mVmDisableMouseIntegrAction->setEnabled (false); 3249 } 3250 } 3251 3252 /** 3253 * @return @c true if successfully performed the requested operation and false 3254 * otherwise. 3255 */ 3256 bool VBoxConsoleWnd::toggleFullscreenMode (bool aOn, bool aSeamless) 3257 { 3258 /* Please note: For some platforms like the Mac, the calling order of the 3259 * functions in this methods is vital. So please be careful on changing 3260 * this. */ 3261 3262 QSize initialSize = size(); 3263 if (aSeamless || mConsole->isAutoresizeGuestActive()) 3264 { 3265 QRect screen = aSeamless ? 3266 QApplication::desktop()->availableGeometry (this) : 3267 QApplication::desktop()->screenGeometry (this); 3268 ULONG64 availBits = mSession.GetMachine().GetVRAMSize() /* vram */ 3269 * _1M /* mb to bytes */ 3270 * 8; /* to bits */ 3271 ULONG guestBpp = mConsole->console().GetDisplay().GetBitsPerPixel(); 3272 ULONG64 usedBits = (screen.width() /* display width */ 3273 * screen.height() /* display height */ 3274 * guestBpp 3275 + _1M * 8) /* current cache per screen - may be changed in future */ 3276 * mSession.GetMachine().GetMonitorCount() /**< @todo fix assumption that all screens have same resolution */ 3277 + 4096 * 8; /* adapter info */ 3278 if (aOn && (availBits < usedBits)) 3279 { 3280 if (aSeamless) 3281 { 3282 vboxProblem().cannotEnterSeamlessMode ( 3283 screen.width(), screen.height(), guestBpp, 3284 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3285 return false; 3286 } 3287 else 3288 { 3289 int result = vboxProblem().cannotEnterFullscreenMode ( 3290 screen.width(), screen.height(), guestBpp, 3291 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3292 if (result == QIMessageBox::Cancel) 3293 return false; 3294 } 3295 } 3296 } 3297 3298 AssertReturn (mConsole, false); 3299 AssertReturn ((mHiddenChildren.empty() == aOn), false); 3300 AssertReturn ((aSeamless && mIsSeamless != aOn) || 3301 (!aSeamless && mIsFullscreen != aOn), false); 3302 if (aOn) 3303 AssertReturn ((aSeamless && !mIsFullscreen) || 3304 (!aSeamless && !mIsSeamless), false); 3305 3306 if (aOn) 3307 { 3308 /* Take the toggle hot key from the menu item. Since 3309 * VBoxGlobal::extractKeyFromActionText gets exactly the 3310 * linked key without the 'Host+' part we are adding it here. */ 3311 QString hotKey = QString ("Host+%1") 3312 .arg (VBoxGlobal::extractKeyFromActionText (aSeamless ? 3313 mVmSeamlessAction->text() : mVmFullscreenAction->text())); 3314 3315 Assert (!hotKey.isEmpty()); 3316 3317 /* Show the info message. */ 3318 bool ok = aSeamless ? 3319 vboxProblem().confirmGoingSeamless (hotKey) : 3320 vboxProblem().confirmGoingFullscreen (hotKey); 3321 if (!ok) 3322 return false; 3323 } 3324 3325 #ifdef Q_WS_MAC 3326 if (!aSeamless) 3327 { 3328 /* Fade to black */ 3329 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken); 3330 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); 3331 } 3332 #endif 3333 3334 if (aSeamless) 3335 { 3336 /* Activate the auto-resize feature required for the seamless mode. */ 3337 if (!mVmAutoresizeGuestAction->isChecked()) 3338 mVmAutoresizeGuestAction->setChecked (true); 3339 3340 /* Activate the mouse integration feature for the seamless mode. */ 3341 if (mVmDisableMouseIntegrAction->isChecked()) 3342 mVmDisableMouseIntegrAction->setChecked (false); 3343 3344 mVmAdjustWindowAction->setEnabled (!aOn); 3345 mVmFullscreenAction->setEnabled (!aOn); 3346 mVmAutoresizeGuestAction->setEnabled (!aOn); 3347 mVmDisableMouseIntegrAction->setEnabled (!aOn); 3348 3349 mConsole->console().GetDisplay().SetSeamlessMode (aOn); 3350 mIsSeamless = aOn; 3351 } 3352 else 3353 { 3354 mIsFullscreen = aOn; 3355 mVmAdjustWindowAction->setEnabled (!aOn); 3356 mVmSeamlessAction->setEnabled (!aOn && mIsSeamlessSupported && mIsGraphicsSupported); 3357 } 3358 3359 bool wasHidden = isHidden(); 3360 3361 /* Temporarily disable the mode-related action to make sure 3362 * user can not leave the mode before he enter it and inside out. */ 3363 aSeamless ? mVmSeamlessAction->setEnabled (false) : 3364 mVmFullscreenAction->setEnabled (false); 3365 3366 /* Calculate initial console size */ 3367 QSize consoleSize; 3368 3369 if (aOn) 3370 { 3371 consoleSize = mConsole->frameSize(); 3372 consoleSize -= QSize (mConsole->frameWidth() * 2, mConsole->frameWidth() * 2); 3373 3374 /* Toggle console to manual resize mode. */ 3375 mConsole->setIgnoreMainwndResize (true); 3376 3377 /* Memorize the maximized state. */ 3378 QDesktopWidget *dtw = QApplication::desktop(); 3379 mWasMax = isWindowMaximized() && 3380 dtw->availableGeometry().width() == frameSize().width() && 3381 dtw->availableGeometry().height() == frameSize().height(); 3382 3383 /* Save the previous scroll-view minimum size before entering 3384 * fullscreen/seamless state to restore this minimum size before 3385 * the exiting fullscreen. Required for correct scroll-view and 3386 * guest display update in SDL mode. */ 3387 mPrevMinSize = mConsole->minimumSize(); 3388 mConsole->setMinimumSize (0, 0); 3389 3390 /* let the widget take the whole available desktop space */ 3391 QRect scrGeo = aSeamless ? 3392 dtw->availableGeometry (this) : dtw->screenGeometry (this); 3393 3394 /* It isn't guaranteed that the guest os set the video mode that 3395 * we requested. So after all the resizing stuff set the clipping 3396 * mask and the spacing shifter to the corresponding values. */ 3397 if (aSeamless) 3398 setViewInSeamlessMode (scrGeo); 3399 3400 #ifdef Q_WS_WIN 3401 mPrevRegion = dtw->screenGeometry (this); 3402 #endif 3403 3404 /* Hide all but the central widget containing the console view. */ 3405 QList <QWidget*> list (findChildren <QWidget*> ()); 3406 QList <QWidget*> excludes; 3407 excludes << centralWidget() << centralWidget()->findChildren <QWidget*> (); 3408 foreach (QWidget *w, list) 3409 { 3410 if (!excludes.contains (w)) 3411 { 3412 if (!w->isHidden()) 3413 { 3414 w->hide(); 3415 mHiddenChildren.append (w); 3416 } 3417 } 3418 } 3419 3420 /* Adjust colors and appearance. */ 3421 mErasePalette = centralWidget()->palette(); 3422 QPalette palette(mErasePalette); 3423 palette.setColor (centralWidget()->backgroundRole(), Qt::black); 3424 centralWidget()->setPalette (palette); 3425 centralWidget()->setAutoFillBackground (!aSeamless); 3426 mConsoleStyle = mConsole->frameStyle(); 3427 mConsole->setFrameStyle (QFrame::NoFrame); 3428 mConsole->setMaximumSize (scrGeo.size()); 3429 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3430 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3431 } 3432 else 3433 { 3434 /* Reset the shifting spacers. */ 3435 mShiftingSpacerLeft->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3436 mShiftingSpacerTop->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3437 mShiftingSpacerRight->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3438 mShiftingSpacerBottom->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3439 3440 /* Restore the previous scroll-view minimum size before the exiting 3441 * fullscreen. Required for correct scroll-view and guest display 3442 * update in SDL mode. */ 3443 mConsole->setMinimumSize (mPrevMinSize); 3444 3445 #ifdef Q_WS_MAC 3446 if (aSeamless) 3447 { 3448 /* Please note: All the stuff below has to be done before the 3449 * window switch back to normal size. Qt changes the winId on the 3450 * fullscreen switch and make this stuff useless with the old 3451 * winId. So please be careful on rearrangement of the method 3452 * calls. */ 3453 /* Undo all mac specific installations */ 3454 ::darwinSetShowsWindowTransparent (this, false); 3455 } 3456 #endif 3457 3458 /* Adjust colors and appearance. */ 3459 clearMask(); 3460 centralWidget()->setPalette (mErasePalette); 3461 centralWidget()->setAutoFillBackground (false); 3462 mConsole->setFrameStyle (mConsoleStyle); 3463 mConsole->setMaximumSize (mConsole->sizeHint()); 3464 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3465 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3466 3467 /* Show everything hidden when going fullscreen. */ 3468 foreach (QPointer <QWidget> child, mHiddenChildren) 3469 if (child) child->show(); 3470 mHiddenChildren.clear(); 3471 } 3472 3473 /* Set flag for waiting host resize if it awaited during mode entering */ 3474 if ((mIsFullscreen || mIsSeamless) && (consoleSize != initialSize)) 3475 mIsWaitingModeResize = true; 3476 3477 if (!aOn) 3478 { 3479 /* Animation takes a bit long, the mini toolbar is still disappearing 3480 * when switched to normal mode so hide it completely */ 3481 mMiniToolBar->hide(); 3482 mMiniToolBar->updateDisplay (false, true); 3483 } 3484 3485 /* Toggle qt full-screen mode */ 3486 switchToFullscreen (aOn, aSeamless); 3487 3488 if (aOn) 3489 { 3490 mMiniToolBar->setSeamlessMode (aSeamless); 3491 mMiniToolBar->updateDisplay (true, true); 3492 } 3493 3494 #ifdef Q_WS_MAC 3495 if (aOn && aSeamless) 3496 { 3497 /* Please note: All the stuff below has to be done after the window has 3498 * switched to fullscreen. Qt changes the winId on the fullscreen 3499 * switch and make this stuff useless with the old winId. So please be 3500 * careful on rearrangement of the method calls. */ 3501 ::darwinSetShowsWindowTransparent (this, true); 3502 } 3503 #endif 3504 3505 /* Send guest size hint */ 3506 mConsole->toggleFSMode (consoleSize); 3507 3508 /* Process all console attributes changes and sub-widget hidings */ 3509 qApp->processEvents(); 3510 3511 if (!mIsWaitingModeResize) 3512 onExitFullscreen(); 3513 3514 /* Unlock FS actions locked during modes toggling */ 3515 QTimer::singleShot (300, this, SLOT (unlockActionsSwitch())); 3516 3517 #ifdef Q_WS_MAC /* wasHidden is wrong on the mac it seems. */ 3518 /** @todo figure out what is really wrong here... */ 3519 if (!wasHidden) 3520 show(); 3521 #else 3522 if (wasHidden) 3523 hide(); 3524 #endif 3525 3526 return true; 3527 } 3528 3529 void VBoxConsoleWnd::switchToFullscreen (bool aOn, bool aSeamless) 3530 { 3531 #ifdef Q_WS_MAC 3532 # ifndef QT_MAC_USE_COCOA 3533 /* setWindowState removes the window group connection somehow. So save it 3534 * temporary. */ 3535 WindowGroupRef g = GetWindowGroup (::darwinToNativeWindow (this)); 3536 # endif /* !QT_MAC_USE_COCOA */ 3537 if (aSeamless) 3538 if (aOn) 3539 { 3540 /* Save for later restoring */ 3541 mNormalGeometry = geometry(); 3542 mSavedFlags = windowFlags(); 3543 /* Remove the frame from the window */ 3544 const QRect fullscreen (qApp->desktop()->screenGeometry (qApp->desktop()->screenNumber (this))); 3545 setParent (0, Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); 3546 setGeometry (fullscreen); 3547 /* Set it maximized */ 3548 setWindowState (windowState() ^ Qt::WindowMaximized); 3549 } 3550 else 3551 { 3552 /* Restore old values */ 3553 setParent (0, mSavedFlags); 3554 setGeometry (mNormalGeometry); 3555 } 3556 else 3557 { 3558 /* Here we are going really fullscreen */ 3559 setWindowState (windowState() ^ Qt::WindowFullScreen); 3560 changePresentationMode (VBoxChangePresentationModeEvent(aOn)); 3561 } 3562 3563 # ifndef QT_MAC_USE_COCOA 3564 /* Reassign the correct window group. */ 3565 SetWindowGroup (::darwinToNativeWindow (this), g); 3566 # endif /* !QT_MAC_USE_COCOA */ 3567 #else 3568 NOREF (aOn); 3569 NOREF (aSeamless); 3570 setWindowState (windowState() ^ Qt::WindowFullScreen); 3571 #endif 3572 } 3573 3574 void VBoxConsoleWnd::setViewInSeamlessMode (const QRect &aTargetRect) 3575 { 3576 #ifndef Q_WS_MAC 3577 /* It isn't guaranteed that the guest os set the video mode that 3578 * we requested. So after all the resizing stuff set the clipping 3579 * mask and the spacing shifter to the corresponding values. */ 3580 QDesktopWidget *dtw = QApplication::desktop(); 3581 QRect sRect = dtw->screenGeometry (this); 3582 QRect aRect (aTargetRect); 3583 mMaskShift.scale (aTargetRect.left(), aTargetRect.top(), Qt::IgnoreAspectRatio); 3584 /* Set the clipping mask */ 3585 mStrictedRegion = aRect; 3586 /* Set the shifting spacer */ 3587 mShiftingSpacerLeft->changeSize (RT_ABS (sRect.left() - aRect.left()), 0, 3588 QSizePolicy::Fixed, QSizePolicy::Preferred); 3589 mShiftingSpacerTop->changeSize (0, RT_ABS (sRect.top() - aRect.top()), 3590 QSizePolicy::Preferred, QSizePolicy::Fixed); 3591 mShiftingSpacerRight->changeSize (RT_ABS (sRect.right() - aRect.right()), 0, 3592 QSizePolicy::Fixed, QSizePolicy::Preferred); 3593 mShiftingSpacerBottom->changeSize (0, RT_ABS (sRect.bottom() - aRect.bottom()), 3594 QSizePolicy::Preferred, QSizePolicy::Fixed); 3595 #else // !Q_WS_MAC 3596 NOREF (aTargetRect); 3597 #endif // !Q_WS_MAC 3598 } 3599 3600 /** 3601 * Closes the console view opened by openView(). 3602 * Does nothing if no console view was opened. 3603 */ 3604 void VBoxConsoleWnd::closeView() 3605 { 3606 LogFlowFuncEnter(); 3607 3608 if (!mConsole) 3609 { 3610 LogFlow (("Already closed!\n")); 3611 LogFlowFuncLeave(); 3612 return; 3613 } 3614 3615 mConsole->detach(); 3616 centralWidget()->layout()->removeWidget (mConsole); 3617 delete mConsole; 3618 mConsole = 0; 3619 mSession.Close(); 3620 mSession.detach(); 3621 3622 LogFlowFuncLeave(); 3623 } 3624 3625 #ifdef VBOX_WITH_DEBUGGER_GUI 3626 3627 /** 3628 * Prepare the Debug menu. 3629 */ 3630 void VBoxConsoleWnd::dbgPrepareDebugMenu() 3631 { 3632 /* The "Logging" item. */ 3633 bool fEnabled = false; 3634 bool fChecked = false; 3635 CConsole console = mSession.GetConsole(); 3636 if (console.isOk()) 3637 { 3638 CMachineDebugger cdebugger = console.GetDebugger(); 3639 if (console.isOk()) 3640 { 3641 fEnabled = true; 3642 fChecked = cdebugger.GetLogEnabled() != FALSE; 3643 } 3644 } 3645 if (fEnabled != mDbgLoggingAction->isEnabled()) 3646 mDbgLoggingAction->setEnabled (fEnabled); 3647 if (fChecked != mDbgLoggingAction->isChecked()) 3648 mDbgLoggingAction->setChecked (fChecked); 3649 } 3650 3651 /** 3652 * Called when the Debug->Statistics... menu item is selected. 3653 */ 3654 void VBoxConsoleWnd::dbgShowStatistics() 3655 { 3656 if (dbgCreated()) 3657 mDbgGuiVT->pfnShowStatistics (mDbgGui); 3658 } 3659 3660 /** 3661 * Called when the Debug->Command Line... menu item is selected. 3662 */ 3663 void VBoxConsoleWnd::dbgShowCommandLine() 3664 { 3665 if (dbgCreated()) 3666 mDbgGuiVT->pfnShowCommandLine (mDbgGui); 3667 } 3668 3669 /** 3670 * Called when the Debug->Logging menu item is selected. 3671 */ 3672 void VBoxConsoleWnd::dbgLoggingToggled (bool aState) 3673 { 3674 NOREF(aState); 3675 CConsole console = mSession.GetConsole(); 3676 if (console.isOk()) 3677 { 3678 CMachineDebugger cdebugger = console.GetDebugger(); 3679 if (console.isOk()) 3680 cdebugger.SetLogEnabled (aState); 3681 } 3682 } 3683 3684 /** 3685 * Ensures that the debugger GUI instance is ready. 3686 * 3687 * @returns true if instance is fine and dandy. 3688 * @returns flase if it's not. 3689 */ 3690 bool VBoxConsoleWnd::dbgCreated() 3691 { 3692 if (mDbgGui) 3693 return true; 3694 3695 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 3696 if (hLdrMod == NIL_RTLDRMOD) 3697 return false; 3698 3699 PFNDBGGUICREATE pfnGuiCreate; 3700 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 3701 if (RT_SUCCESS (rc)) 3702 { 3703 ISession *pISession = mSession.raw(); 3704 rc = pfnGuiCreate (pISession, &mDbgGui, &mDbgGuiVT); 3705 if (RT_SUCCESS (rc)) 3706 { 3707 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (mDbgGuiVT->u32Version, DBGGUIVT_VERSION) || 3708 mDbgGuiVT->u32EndVersion == mDbgGuiVT->u32Version) 3709 { 3710 mDbgGuiVT->pfnSetParent (mDbgGui, (QWidget*) this); 3711 mDbgGuiVT->pfnSetMenu (mDbgGui, (QMenu*) mDbgMenu); 3712 dbgAdjustRelativePos(); 3713 return true; 3714 } 3715 3716 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 3717 mDbgGuiVT->u32Version, mDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3718 } 3719 else 3720 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 3721 } 3722 else 3723 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 3724 3725 mDbgGui = 0; 3726 mDbgGuiVT = 0; 3727 return false; 3728 } 3729 3730 /** 3731 * Destroys the debugger GUI instacne if it has been created. 3732 */ 3733 void VBoxConsoleWnd::dbgDestroy() 3734 { 3735 if (mDbgGui) 3736 { 3737 mDbgGuiVT->pfnDestroy (mDbgGui); 3738 mDbgGui = 0; 3739 mDbgGuiVT = 0; 3740 } 3741 } 3742 3743 /** 3744 * Tells the debugger GUI that the console window has moved or been resized. 3745 */ 3746 void VBoxConsoleWnd::dbgAdjustRelativePos() 3747 { 3748 if (mDbgGui) 3749 { 3750 QRect rct = frameGeometry(); 3751 mDbgGuiVT->pfnAdjustRelativePos (mDbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 3752 } 3753 } 3754 3755 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3756 3757 VBoxNetworkDialog::VBoxNetworkDialog (QWidget *aParent, CSession &aSession) 3758 : QIWithRetranslateUI <QDialog> (aParent) 3759 , mSettings (0) 3760 , mSession (aSession) 3761 { 3762 setModal (true); 3763 /* Setup Dialog's options */ 3764 setWindowIcon (QIcon (":/nw_16px.png")); 3765 setSizeGripEnabled (true); 3766 3767 /* Setup main dialog's layout */ 3768 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3769 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3770 mainLayout->setSpacing (10); 3771 3772 /* Setup settings layout */ 3773 mSettings = new VBoxVMSettingsNetworkPage (true); 3774 mSettings->setOrderAfter (this); 3775 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3776 mSettings->getFrom (aSession.GetMachine()); 3777 mainLayout->addWidget (mSettings); 3778 3779 /* Setup button's layout */ 3780 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3781 3782 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3783 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3784 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3785 mainLayout->addWidget (buttonBox); 3786 3787 retranslateUi(); 3788 } 3789 3790 void VBoxNetworkDialog::retranslateUi() 3791 { 3792 setWindowTitle (tr ("Network Adapters")); 3793 } 3794 3795 void VBoxNetworkDialog::accept() 3796 { 3797 mSettings->putBackTo(); 3798 CMachine machine = mSession.GetMachine(); 3799 machine.SaveSettings(); 3800 if (!machine.isOk()) 3801 vboxProblem().cannotSaveMachineSettings (machine); 3802 QDialog::accept(); 3803 } 3804 3805 void VBoxNetworkDialog::showEvent (QShowEvent *aEvent) 3806 { 3807 resize (450, 300); 3808 VBoxGlobal::centerWidget (this, parentWidget()); 3809 setMinimumWidth (400); 3810 QDialog::showEvent (aEvent); 3811 } 3812 3813 VBoxSFDialog::VBoxSFDialog (QWidget *aParent, CSession &aSession) 3814 : QIWithRetranslateUI <QDialog> (aParent) 3815 , mSettings (0) 3816 , mSession (aSession) 3817 { 3818 setModal (true); 3819 /* Setup Dialog's options */ 3820 setWindowIcon (QIcon (":/select_file_16px.png")); 3821 setSizeGripEnabled (true); 3822 3823 /* Setup main dialog's layout */ 3824 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3825 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3826 mainLayout->setSpacing (10); 3827 3828 /* Setup settings layout */ 3829 mSettings = new VBoxVMSettingsSF (MachineType | ConsoleType, this); 3830 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3831 mSettings->getFromConsole (aSession.GetConsole()); 3832 mSettings->getFromMachine (aSession.GetMachine()); 3833 mainLayout->addWidget (mSettings); 3834 3835 /* Setup button's layout */ 3836 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3837 3838 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3839 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3840 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3841 mainLayout->addWidget (buttonBox); 3842 3843 retranslateUi(); 3844 } 3845 3846 void VBoxSFDialog::retranslateUi() 3847 { 3848 setWindowTitle (tr ("Shared Folders")); 3849 } 3850 3851 void VBoxSFDialog::accept() 3852 { 3853 mSettings->putBackToConsole(); 3854 mSettings->putBackToMachine(); 3855 CMachine machine = mSession.GetMachine(); 3856 machine.SaveSettings(); 3857 if (!machine.isOk()) 3858 vboxProblem().cannotSaveMachineSettings (machine); 3859 QDialog::accept(); 3860 } 3861 3862 void VBoxSFDialog::showEvent (QShowEvent *aEvent) 3863 { 3864 resize (450, 300); 3865 VBoxGlobal::centerWidget (this, parentWidget()); 3866 setMinimumWidth (400); 3867 QDialog::showEvent (aEvent); 3868 } 3869 3870 #include "VBoxConsoleWnd.moc" 207 connect(machineWindowWrapper()->machineView(), SIGNAL(machineStateChanged(KMachineState)), this, SLOT(sltUpdateMachineState(KMachineState))); 208 connect(machineWindowWrapper()->machineView(), SIGNAL(additionsStateChanged(const QString&, bool, bool, bool)), 209 this, SLOT(sltUpdateAdditionsState(const QString &, bool, bool, bool))); 210 connect(machineWindowWrapper()->machineView(), SIGNAL(mouseStateChanged(int)), this, SLOT(sltUpdateMouseState(int))); 211 212 /* Re-request all the static values finally after view is really opened and attached: */ 213 updateAppearanceOf(UIVisualElement_VirtualizationStuff); 214 } 215 216 void UIMachineLogicNormal::cleanupMachineWindow() 217 { 218 if (!machineWindowWrapper()) 219 return; 220 221 // TODO: What should be done on window destruction? 222 //machineWindowWrapper()->machineView()->detach(); 223 //m_session.Close(); 224 //m_session.detach(); 225 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass declaration4 * UIMachineLogicNormal class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2009Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef __VBoxConsoleWnd_h__ 24 #define __VBoxConsoleWnd_h__ 25 26 /* Global includes */ 27 #include <QColor> 28 #include <QDialog> 29 #include <QMainWindow> 30 #include <QMap> 31 #include <QMenu> 32 #include <QPointer> 23 #ifndef __UIMachineLogicNormal_h__ 24 #define __UIMachineLogicNormal_h__ 33 25 34 26 /* Local includes */ 35 #include "COMDefs.h" 36 #include "QIWithRetranslateUI.h" 37 #include "VBoxProblemReporter.h" 38 #include "VBoxHelpActions.h" 39 40 #ifdef VBOX_WITH_DEBUGGER_GUI 41 # include <VBox/dbggui.h> 42 #endif 43 #ifdef Q_WS_MAC 44 # include <ApplicationServices/ApplicationServices.h> 45 # ifndef QT_MAC_USE_COCOA 46 # include <Carbon/Carbon.h> 47 # endif /* !QT_MAC_USE_COCOA */ 48 #endif 49 50 /* Global forwards */ 51 class QAction; 52 class QActionGroup; 53 class QLabel; 54 class QSpacerItem; 55 class QIWidgetValidator; 27 #include "UIMachineLogic.h" 56 28 57 29 /* Local forwards */ 58 class QIMenu; 59 class QIStateIndicator; 60 class VBoxChangeDockIconUpdateEvent; 61 class VBoxChangePresentationModeEvent; 62 class VBoxConsoleView; 63 class VBoxMiniToolBar; 64 class VBoxSwitchMenu; 65 class VBoxUSBMenu; 30 class UIActionsPool; 66 31 67 class VBoxConsoleWnd : public QIWithRetranslateUI2 <QMainWindow>32 class UIMachineLogicNormal : public UIMachineLogic 68 33 { 69 34 Q_OBJECT; 70 35 71 public:72 73 VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent = 0, Qt::WindowFlags aFlags = Qt::Window);74 virtual ~VBoxConsoleWnd();75 76 bool isWindowMaximized() const77 {78 #ifdef Q_WS_MAC79 /* On Mac OS X we didn't really jump to the fullscreen mode but80 * maximize the window. This situation has to be considered when81 * checking for maximized or fullscreen mode. */82 return !isTrueSeamless() && QMainWindow::isMaximized();83 #else /* Q_WS_MAC */84 return QMainWindow::isMaximized();85 #endif /* Q_WS_MAC */86 }87 bool isWindowFullScreen() const88 {89 #ifdef Q_WS_MAC90 /* On Mac OS X we didn't really jump to the fullscreen mode but91 * maximize the window. This situation has to be considered when92 * checking for maximized or fullscreen mode. */93 return isTrueFullscreen() || isTrueSeamless();94 #else /* Q_WS_MAC */95 return QMainWindow::isFullScreen();96 #endif /* Q_WS_MAC */97 }98 bool isTrueFullscreen() const { return mIsFullscreen; }99 bool isTrueSeamless() const { return mIsSeamless; }100 101 KMachineState machineState() const { return mMachineState; }102 103 bool openView (const CSession &aSession);104 105 void setMouseIntegrationLocked (bool aDisabled);106 107 void popupMainMenu (bool aCenter);108 109 void installGuestAdditionsFrom (const QString &aSource);110 111 void setMask (const QRegion &aRegion);112 void clearMask();113 114 /* informs that the guest display is resized */115 void onDisplayResize (ulong aHeight, ulong aWidth);116 117 #ifdef VBOX_WITH_VIDEOHWACCEL118 /* used for obtaining the extradata settings */119 CSession &session() { return mSession; }120 #endif121 signals:122 123 void closing();124 125 36 protected: 126 37 127 bool event (QEvent *aEvent); 128 void closeEvent (QCloseEvent *aEvent); 129 #ifdef Q_WS_X11 130 bool x11Event (XEvent *aEvent); 131 #endif 132 133 void retranslateUi(); 38 /* Normal machine logic constructor: */ 39 UIMachineLogicNormal(QObject *pParent, 40 const CSession &session, 41 UIActionsPool *pActionsPool); 42 /* Normal machine logic destructor: */ 43 virtual ~UIMachineLogicNormal(); 134 44 135 45 private slots: 136 46 137 void finalizeOpenView(); 138 void tryClose(); 139 140 void vmFullscreen (bool aOn); 141 void vmSeamless (bool aOn); 142 void vmAutoresizeGuest (bool aOn); 143 void vmAdjustWindow(); 144 void vmDisableMouseIntegration (bool aOff); 145 void vmTypeCAD(); 146 #ifdef Q_WS_X11 147 void vmTypeCABS(); 148 #endif 149 void vmTakeSnapshot(); 150 void vmShowInfoDialog(); 151 void vmReset(); 152 void vmPause (bool aOn); 153 void vmACPIShutdown(); 154 void vmClose(); 155 156 void devicesSwitchVrdp (bool aOn); 157 void devicesOpenNetworkDialog(); 158 void devicesOpenSFDialog(); 159 void devicesInstallGuestAdditions(); 160 161 void prepareStorageMenu(); 162 void prepareNetworkMenu(); 163 void prepareSFMenu(); 164 165 void mountMedium(); 166 void switchUSB (QAction *aAction); 167 168 void showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent); 169 170 void updateDeviceLights(); 171 void updateMachineState (KMachineState aState); 172 void updateMouseState (int aState); 173 void updateAdditionsState (const QString &aVersion, bool aActive, 174 bool aSeamlessSupported, bool aGraphicsSupported); 175 void updateNetworkAdaptersState(); 176 void updateUsbState(); 177 void updateMediaDriveState (VBoxDefs::MediumType aType); 178 void updateSharedFoldersState(); 179 180 void onExitFullscreen(); 181 void unlockActionsSwitch(); 182 183 void mtExitMode(); 184 void mtCloseVM(); 185 void mtMaskUpdate(); 186 187 void changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent); 188 void changePresentationMode (const VBoxChangePresentationModeEvent &aEvent); 189 void processGlobalSettingChange (const char *aPublicName, const char *aName); 190 191 #ifdef VBOX_WITH_DEBUGGER_GUI 192 void dbgPrepareDebugMenu(); 193 void dbgShowStatistics(); 194 void dbgShowCommandLine(); 195 void dbgLoggingToggled (bool aBool); 196 #endif 47 /* Status-bar LED funtionality: */ 48 void sltPrepareNetworkAdaptersMenu(); 49 void sltPrepareSharedFoldersMenu(); 197 50 198 51 private: 199 52 200 enum /* Stuff */ 201 { 202 HardDiskStuff = 0x01, 203 DVDStuff = 0x02, 204 FloppyStuff = 0x04, 205 PauseAction = 0x08, 206 NetworkStuff = 0x10, 207 DisableMouseIntegrAction = 0x20, 208 Caption = 0x40, 209 USBStuff = 0x80, 210 VRDPStuff = 0x100, 211 SharedFolderStuff = 0x200, 212 VirtualizationStuff = 0x400, 213 AllStuff = 0xFFFF, 214 }; 53 /* Update routines: */ 54 void updateAppearanceOf(int); 215 55 216 void checkRequiredFeatures(); 217 void activateUICustomizations(); 56 /* Prepare helpers: */ 57 void prepareActionConnections(); 58 void prepareMachineWindow(); 59 //void loadLogicSettings(); 218 60 219 void updateAppearanceOf (int aElement); 61 /* Cleanup helpers: */ 62 //void saveLogicSettings(); 63 void cleanupMachineWindow(); 220 64 221 bool toggleFullscreenMode (bool aOn, bool aSeamless); 222 void switchToFullscreen (bool aOn, bool aSeamless); 223 void setViewInSeamlessMode (const QRect &aTargetRect); 224 225 void closeView(); 226 227 #ifdef VBOX_WITH_DEBUGGER_GUI 228 bool dbgCreated(); 229 void dbgDestroy(); 230 void dbgAdjustRelativePos(); 231 #endif 232 233 /* COM Variables */ 234 CSession mSession; 235 236 /* Machine State */ 237 KMachineState mMachineState; 238 239 /* Window Variables */ 240 QString mCaptionPrefix; 241 int mConsoleStyle; 242 243 /* Menu items */ 244 QIMenu *mMainMenu; 245 QMenu *mVMMenu; 246 QMenu *mVMMenuMini; 247 QMenu *mDevicesMenu; 248 QMenu *mDevicesCDMenu; 249 QMenu *mDevicesFDMenu; 250 QMenu *mDevicesNetworkMenu; 251 QMenu *mDevicesSFMenu; 252 VBoxUSBMenu *mDevicesUSBMenu; 253 VBoxSwitchMenu *mVmDisMouseIntegrMenu; 254 #if 0 /* todo: allow to setup */ 255 VBoxSwitchMenu *mDevicesVRDPMenu; 256 VBoxSwitchMenu *mVmAutoresizeMenu; 257 #endif 258 #ifdef VBOX_WITH_DEBUGGER_GUI 259 QMenu *mDbgMenu; 260 #endif 261 QMenu *mHelpMenu; 262 263 QActionGroup *mRunningActions; 264 QActionGroup *mRunningOrPausedActions; 265 266 /* Machine actions */ 267 QAction *mVmFullscreenAction; 268 QAction *mVmSeamlessAction; 269 QAction *mVmAutoresizeGuestAction; 270 QAction *mVmAdjustWindowAction; 271 QAction *mVmDisableMouseIntegrAction; 272 QAction *mVmTypeCADAction; 273 #ifdef Q_WS_X11 274 QAction *mVmTypeCABSAction; 275 #endif 276 QAction *mVmTakeSnapshotAction; 277 QAction *mVmShowInformationDlgAction; 278 QAction *mVmResetAction; 279 QAction *mVmPauseAction; 280 QAction *mVmACPIShutdownAction; 281 QAction *mVmCloseAction; 282 283 /* Devices actions */ 284 QAction *mDevicesNetworkDialogAction; 285 QAction *mDevicesSFDialogAction; 286 QAction *mDevicesSwitchVrdpSeparator; 287 QAction *mDevicesSwitchVrdpAction; 288 QAction *mDevicesInstallGuestToolsAction; 289 290 #ifdef VBOX_WITH_DEBUGGER_GUI 291 /* Debugger actions */ 292 QAction *mDbgStatisticsAction; 293 QAction *mDbgCommandLineAction; 294 QAction *mDbgLoggingAction; 295 #endif 296 297 /* Help actions */ 298 VBoxHelpActions mHelpActions; 299 300 /* Widgets */ 301 VBoxConsoleView *mConsole; 302 VBoxMiniToolBar *mMiniToolBar; 303 #ifdef VBOX_WITH_DEBUGGER_GUI 304 /** The handle to the debugger gui. */ 305 PDBGGUI mDbgGui; 306 /** The virtual method table for the debugger GUI. */ 307 PCDBGGUIVT mDbgGuiVT; 308 #endif 309 310 /* Timer to update LEDs */ 311 QTimer *mIdleTimer; 312 313 /* LEDs */ 314 QIStateIndicator *mHDLed; 315 QIStateIndicator *mCDLed; 316 #if 0 /* todo: allow to setup */ 317 QIStateIndicator *mFDLed; 318 #endif 319 QIStateIndicator *mNetLed; 320 QIStateIndicator *mUSBLed; 321 QIStateIndicator *mSFLed; 322 QIStateIndicator *mVirtLed; 323 QIStateIndicator *mMouseLed; 324 QIStateIndicator *mHostkeyLed; 325 QWidget *mHostkeyLedContainer; 326 QLabel *mHostkeyName; 327 #if 0 /* todo: allow to setup */ 328 QIStateIndicator *mVrdpLed; 329 QIStateIndicator *mAutoresizeLed; 330 #endif 331 332 /* Normal Mode */ 333 QRect mNormalGeo; 334 335 /* Fullscreen/Seamless Mode */ 336 QList < QPointer <QWidget> > mHiddenChildren; 337 QSpacerItem *mShiftingSpacerLeft; 338 QSpacerItem *mShiftingSpacerTop; 339 QSpacerItem *mShiftingSpacerRight; 340 QSpacerItem *mShiftingSpacerBottom; 341 QPalette mErasePalette; 342 QSize mPrevMinSize; 343 QSize mMaskShift; 344 QRegion mStrictedRegion; 345 #ifdef Q_WS_WIN 346 QRegion mPrevRegion; 347 #endif 348 #ifdef Q_WS_MAC 349 //QRegion mCurrRegion; 350 # ifndef QT_MAC_USE_COCOA 351 //EventHandlerRef mDarwinRegionEventHandlerRef; 352 # endif 353 /* For seamless maximizing */ 354 QRect mNormalGeometry; 355 Qt::WindowFlags mSavedFlags; 356 /* For the fade effect if the the window goes fullscreen */ 357 CGDisplayFadeReservationToken mFadeToken; 358 #endif 359 360 /* Different bool flags */ 361 bool mIsOpenViewFinished : 1; 362 bool mIsFirstTimeStarted : 1; 363 bool mIsAutoSaveMedia : 1; 364 bool mNoAutoClose : 1; 365 bool mIsFullscreen : 1; 366 bool mIsSeamless : 1; 367 bool mIsSeamlessSupported : 1; 368 bool mIsGraphicsSupported : 1; 369 bool mIsWaitingModeResize : 1; 370 bool mWasMax : 1; 65 friend class UIMachineLogic; 371 66 }; 372 67 373 /* We want to make the first action highlighted but not 374 * selected, but Qt makes the both or neither one of this, 375 * so, just move the focus to the next eligible object, 376 * which will be the first menu action. This little 377 * subclass made only for that purpose. */ 378 class QIMenu : public QMenu 379 { 380 Q_OBJECT; 381 382 public: 383 384 QIMenu (QWidget *aParent) : QMenu (aParent) {} 385 386 void selectFirstAction() { QMenu::focusNextChild(); } 387 }; 388 389 class VBoxSettingsPage; 390 class VBoxNetworkDialog : public QIWithRetranslateUI <QDialog> 391 { 392 Q_OBJECT; 393 394 public: 395 396 VBoxNetworkDialog (QWidget *aParent, CSession &aSession); 397 398 protected: 399 400 void retranslateUi(); 401 402 protected slots: 403 404 virtual void accept(); 405 406 protected: 407 408 void showEvent (QShowEvent *aEvent); 409 410 private: 411 412 VBoxSettingsPage *mSettings; 413 CSession &mSession; 414 }; 415 416 class VBoxVMSettingsSF; 417 class VBoxSFDialog : public QIWithRetranslateUI <QDialog> 418 { 419 Q_OBJECT; 420 421 public: 422 423 VBoxSFDialog (QWidget *aParent, CSession &aSession); 424 425 protected: 426 427 void retranslateUi(); 428 429 protected slots: 430 431 virtual void accept(); 432 433 protected: 434 435 void showEvent (QShowEvent *aEvent); 436 437 private: 438 439 VBoxVMSettingsSF *mSettings; 440 CSession &mSession; 441 }; 442 443 #endif // __VBoxConsoleWnd_h__ 68 #endif // __UIMachineLogicNormal_h__ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleViewclass implementation4 * UIMachineViewNormal class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 2 2006-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 24 # include "precomp.h" 25 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 26 #include <VBox/VBoxVideo.h> 23 /* Global includes */ 24 #include <QApplication> 25 #include <QDesktopWidget> 27 26 28 #include "VBoxConsoleView.h" 29 #include "VBoxConsoleWnd.h" 30 #include "VBoxUtils.h" 27 /* Local includes */ 28 #include "VBoxGlobal.h" 29 #include "UIActionsPool.h" 30 #include "UIMachineLogic.h" 31 #include "UIMachineWindow.h" 32 #include "UIMachineViewNormal.h" 31 33 32 #include "VBoxFrameBuffer.h" 33 #include "VBoxGlobal.h" 34 #include "VBoxProblemReporter.h" 34 UIMachineViewNormal::UIMachineViewNormal( UIMachineWindow *pMachineWindow 35 , VBoxDefs::RenderMode renderMode 36 #ifdef VBOX_WITH_VIDEOHWACCEL 37 , bool bAccelerate2DVideo 38 #endif 39 ) 40 : UIMachineView( pMachineWindow 41 , renderMode 42 #ifdef VBOX_WITH_VIDEOHWACCEL 43 , bAccelerate2DVideo 44 #endif 45 ) 46 { 47 /* Connect actions to view: */ 48 connect(machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize), 49 SIGNAL(toggled(bool)), this, SLOT(sltToggleGuestAutoresize(bool))); 35 50 36 #ifdef Q_WS_PM 37 #include "QIHotKeyEdit.h" 38 #endif 39 40 /* Qt includes */ 41 #include <QMenuBar> 42 #include <QDesktopWidget> 43 #include <QTimer> 44 #include <QStatusBar> 45 #include <QPainter> 46 #include <QBitmap> 47 48 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ /** @todo Move this further down! Requires some cleanup below though, so later. */ 49 50 #ifdef Q_WS_WIN 51 // VBox/cdefs.h defines these: 52 #undef LOWORD 53 #undef HIWORD 54 #undef LOBYTE 55 #undef HIBYTE 56 #include <windows.h> 57 #endif 58 59 #ifdef Q_WS_X11 60 #include <QX11Info> 61 // We need to capture some X11 events directly which 62 // requires the XEvent structure to be defined. However, 63 // including the Xlib header file will cause some nasty 64 // conflicts with Qt. Therefore we use the following hack 65 // to redefine those conflicting identifiers. 66 #define XK_XKB_KEYS 67 #define XK_MISCELLANY 68 #include <X11/Xlib.h> 69 #include <X11/Xutil.h> 70 #include <X11/XKBlib.h> 71 #include <X11/keysym.h> 72 #ifdef KeyPress 73 const int XFocusOut = FocusOut; 74 const int XFocusIn = FocusIn; 75 const int XKeyPress = KeyPress; 76 const int XKeyRelease = KeyRelease; 77 #undef KeyRelease 78 #undef KeyPress 79 #undef FocusOut 80 #undef FocusIn 81 #endif 82 #include "XKeyboard.h" 83 #ifndef VBOX_WITHOUT_XCURSOR 84 # include <X11/Xcursor/Xcursor.h> 85 #endif 86 #endif // Q_WS_X11 87 88 #if defined (Q_WS_MAC) 89 # include "DockIconPreview.h" 90 # include "DarwinKeyboard.h" 91 # ifdef QT_MAC_USE_COCOA 92 # include "darwin/VBoxCocoaApplication.h" 93 # elif defined(VBOX_WITH_HACKED_QT) 94 # include "QIApplication.h" 95 # endif 96 # include <Carbon/Carbon.h> 97 # include <VBox/err.h> 98 #endif /* defined (Q_WS_MAC) */ 99 100 #if defined (Q_WS_WIN32) 101 102 static HHOOK gKbdHook = NULL; 103 static VBoxConsoleView *gView = 0; 104 105 LRESULT CALLBACK VBoxConsoleView::lowLevelKeyboardProc (int nCode, 106 WPARAM wParam, LPARAM lParam) 107 { 108 Assert (gView); 109 if (gView && nCode == HC_ACTION && 110 gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam)) 111 return 1; 112 113 return CallNextHookEx (NULL, nCode, wParam, lParam); 51 /* Connect view to handlers */ 52 connect(this, SIGNAL(additionsStateChanged(const QString&, bool, bool, bool)), 53 this, SLOT(sltAdditionsStateChanged(const QString &, bool, bool, bool))); 114 54 } 115 55 116 #endif 117 118 #if defined (Q_WS_MAC) 119 # if defined (QT_MAC_USE_COCOA) 120 /** 121 * Event handler callback for Mac OS X, Cocoa variant. 122 * 123 * (Registered with and called from VBoxCocoaApplication.) 124 * 125 * @returns true if the event should be dropped, false if it should be passed 126 * along. 127 * @param pvCocoaEvent The Cocoa event object. 128 * @param pvCarbonEvent The Carbon event object reference. 129 * @param pvUser The user argument. 130 */ 131 /* static */ 132 bool VBoxConsoleView::darwinEventHandlerProc (const void *pvCocoaEvent, 133 const void *pvCarbonEvent, 134 void *pvUser) 56 void UIMachineViewNormal::normalizeGeometry(bool bAdjustPosition /* = false */) 135 57 { 136 VBoxConsoleView *view = (VBoxConsoleView *)pvUser; 137 EventRef inEvent = (EventRef)pvCarbonEvent; 138 UInt32 eventClass = ::GetEventClass (inEvent); 139 140 #if 0 141 /* For debugging events. */ 142 if (eventClass != 'cute') 143 ::VBoxCocoaApplication_printEvent ("view: ", pvCocoaEvent); 144 #endif 145 /* Check if this is an application key combo. In that case we will not pass 146 the event to the guest, but let the host process it. */ 147 if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent)) 148 return false; 149 150 /* 151 * All keyboard class events needs to be handled. 152 */ 153 if (eventClass == kEventClassKeyboard) 154 { 155 if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent)) 156 return true; 157 } 158 /* Pass the event along. */ 159 return false; 160 } 161 162 # elif !defined (VBOX_WITH_HACKED_QT) 163 /** 164 * Event handler callback for Mac OS X. 165 */ 166 /* static */ 167 pascal OSStatus VBoxConsoleView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef, 168 EventRef inEvent, void *inUserData) 169 { 170 VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData); 171 UInt32 eventClass = ::GetEventClass (inEvent); 172 173 /* For debugging events */ 174 /* 175 if (eventClass != 'cute') 176 ::darwinDebugPrintEvent ("view: ", inEvent); 177 */ 178 179 /* Not sure but this seems an triggered event if the spotlight searchbar is 180 * displayed. So flag that the host key isn't pressed alone. */ 181 if ( eventClass == 'cgs ' 182 && view->mIsHostkeyPressed 183 && ::GetEventKind (inEvent) == 0x15) 184 view->mIsHostkeyAlone = false; 185 186 if (eventClass == kEventClassKeyboard) 187 { 188 if (view->darwinKeyboardEvent (NULL, inEvent)) 189 return 0; 190 } 191 /* 192 * Command-H and Command-Q aren't properly disabled yet, and it's still 193 * possible to use the left command key to invoke them when the keyboard 194 * is captured. We discard the events these if the keyboard is captured 195 * as a half measure to prevent unexpected behaviour. However, we don't 196 * get any key down/up events, so these combinations are dead to the guest... 197 */ 198 else if (eventClass == kEventClassCommand) 199 { 200 if (view->mKbdCaptured) 201 return 0; 202 } 203 return ::CallNextEventHandler (inHandlerCallRef, inEvent); 204 } 205 206 # else /* VBOX_WITH_HACKED_QT */ 207 /** 208 * Event handler callback for Mac OS X. 209 */ 210 /* static */ 211 bool VBoxConsoleView::macEventFilter (EventRef inEvent, void *inUserData) 212 { 213 VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData); 214 UInt32 eventClass = ::GetEventClass (inEvent); 215 UInt32 eventKind = ::GetEventKind (inEvent); 216 217 /* For debugging events */ 218 /* 219 if (!(eventClass == 'cute')) 220 ::darwinDebugPrintEvent ("view: ", inEvent); 221 */ 222 223 /* Not sure but this seems an triggered event if the spotlight searchbar is 224 * displayed. So flag that the host key isn't pressed alone. */ 225 if (eventClass == 'cgs ' && eventKind == 0x15 && 226 view->mIsHostkeyPressed) 227 view->mIsHostkeyAlone = false; 228 229 if (eventClass == kEventClassKeyboard) 230 { 231 if (view->darwinKeyboardEvent (NULL, inEvent)) 232 return true; 233 } 234 return false; 235 } 236 # endif /* VBOX_WITH_HACKED_QT */ 237 238 #endif /* Q_WS_MAC */ 239 240 /** Guest mouse pointer shape change event. */ 241 class MousePointerChangeEvent : public QEvent 242 { 243 public: 244 MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot, 245 uint width, uint height, 246 const uchar *shape) : 247 QEvent ((QEvent::Type) VBoxDefs::MousePointerChangeEventType), 248 vis (visible), alph (alpha), xh (xhot), yh (yhot), w (width), h (height), 249 data (NULL) 250 { 251 // make a copy of shape 252 uint dataSize = ((((width + 7) / 8 * height) + 3) & ~3) + width * 4 * height; 253 254 if (shape) { 255 data = new uchar [dataSize]; 256 memcpy ((void *) data, (void *) shape, dataSize); 257 } 258 } 259 ~MousePointerChangeEvent() 260 { 261 if (data) delete[] data; 262 } 263 bool isVisible() const { return vis; } 264 bool hasAlpha() const { return alph; } 265 uint xHot() const { return xh; } 266 uint yHot() const { return yh; } 267 uint width() const { return w; } 268 uint height() const { return h; } 269 const uchar *shapeData() const { return data; } 270 private: 271 bool vis, alph; 272 uint xh, yh, w, h; 273 const uchar *data; 274 }; 275 276 /** Guest mouse absolute positioning capability change event. */ 277 class MouseCapabilityEvent : public QEvent 278 { 279 public: 280 MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor) : 281 QEvent ((QEvent::Type) VBoxDefs::MouseCapabilityEventType), 282 can_abs (supportsAbsolute), 283 needs_host_cursor (needsHostCursor) {} 284 bool supportsAbsolute() const { return can_abs; } 285 bool needsHostCursor() const { return needs_host_cursor; } 286 private: 287 bool can_abs; 288 bool needs_host_cursor; 289 }; 290 291 /** Machine state change. */ 292 class StateChangeEvent : public QEvent 293 { 294 public: 295 StateChangeEvent (KMachineState state) : 296 QEvent ((QEvent::Type) VBoxDefs::MachineStateChangeEventType), 297 s (state) {} 298 KMachineState machineState() const { return s; } 299 private: 300 KMachineState s; 301 }; 302 303 /** Guest Additions property changes. */ 304 class GuestAdditionsEvent : public QEvent 305 { 306 public: 307 GuestAdditionsEvent (const QString &aOsTypeId, 308 const QString &aAddVersion, 309 bool aAddActive, 310 bool aSupportsSeamless, 311 bool aSupportsGraphics) : 312 QEvent ((QEvent::Type) VBoxDefs::AdditionsStateChangeEventType), 313 mOsTypeId (aOsTypeId), mAddVersion (aAddVersion), 314 mAddActive (aAddActive), mSupportsSeamless (aSupportsSeamless), 315 mSupportsGraphics (aSupportsGraphics) {} 316 const QString &osTypeId() const { return mOsTypeId; } 317 const QString &additionVersion() const { return mAddVersion; } 318 bool additionActive() const { return mAddActive; } 319 bool supportsSeamless() const { return mSupportsSeamless; } 320 bool supportsGraphics() const { return mSupportsGraphics; } 321 private: 322 QString mOsTypeId; 323 QString mAddVersion; 324 bool mAddActive; 325 bool mSupportsSeamless; 326 bool mSupportsGraphics; 327 }; 328 329 /** DVD/Floppy drive change event */ 330 class MediaDriveChangeEvent : public QEvent 331 { 332 public: 333 MediaDriveChangeEvent (VBoxDefs::MediumType aType) 334 : QEvent ((QEvent::Type) VBoxDefs::MediaDriveChangeEventType) 335 , mType (aType) {} 336 VBoxDefs::MediumType type() const { return mType; } 337 private: 338 VBoxDefs::MediumType mType; 339 }; 340 341 /** Menu activation event */ 342 class ActivateMenuEvent : public QEvent 343 { 344 public: 345 ActivateMenuEvent (QAction *aData) : 346 QEvent ((QEvent::Type) VBoxDefs::ActivateMenuEventType), 347 mAction (aData) {} 348 QAction *action() const { return mAction; } 349 private: 350 QAction *mAction; 351 }; 352 353 /** VM Runtime error event */ 354 class RuntimeErrorEvent : public QEvent 355 { 356 public: 357 RuntimeErrorEvent (bool aFatal, const QString &aErrorID, 358 const QString &aMessage) : 359 QEvent ((QEvent::Type) VBoxDefs::RuntimeErrorEventType), 360 mFatal (aFatal), mErrorID (aErrorID), mMessage (aMessage) {} 361 bool fatal() const { return mFatal; } 362 QString errorID() const { return mErrorID; } 363 QString message() const { return mMessage; } 364 private: 365 bool mFatal; 366 QString mErrorID; 367 QString mMessage; 368 }; 369 370 /** Modifier key change event */ 371 class ModifierKeyChangeEvent : public QEvent 372 { 373 public: 374 ModifierKeyChangeEvent (bool fNumLock, bool fCapsLock, bool fScrollLock) : 375 QEvent ((QEvent::Type) VBoxDefs::ModifierKeyChangeEventType), 376 mNumLock (fNumLock), mCapsLock (fCapsLock), mScrollLock (fScrollLock) {} 377 bool numLock() const { return mNumLock; } 378 bool capsLock() const { return mCapsLock; } 379 bool scrollLock() const { return mScrollLock; } 380 private: 381 bool mNumLock, mCapsLock, mScrollLock; 382 }; 383 384 /** Network adapter change event */ 385 class NetworkAdapterChangeEvent : public QEvent 386 { 387 public: 388 NetworkAdapterChangeEvent (INetworkAdapter *aAdapter) : 389 QEvent ((QEvent::Type) VBoxDefs::NetworkAdapterChangeEventType), 390 mAdapter (aAdapter) {} 391 INetworkAdapter* networkAdapter() { return mAdapter; } 392 private: 393 INetworkAdapter *mAdapter; 394 }; 395 396 /** USB controller state change event */ 397 class USBControllerStateChangeEvent : public QEvent 398 { 399 public: 400 USBControllerStateChangeEvent() 401 : QEvent ((QEvent::Type) VBoxDefs::USBCtlStateChangeEventType) {} 402 }; 403 404 /** USB device state change event */ 405 class USBDeviceStateChangeEvent : public QEvent 406 { 407 public: 408 USBDeviceStateChangeEvent (const CUSBDevice &aDevice, bool aAttached, 409 const CVirtualBoxErrorInfo &aError) : 410 QEvent ((QEvent::Type) VBoxDefs::USBDeviceStateChangeEventType), 411 mDevice (aDevice), mAttached (aAttached), mError (aError) {} 412 CUSBDevice device() const { return mDevice; } 413 bool attached() const { return mAttached; } 414 CVirtualBoxErrorInfo error() const { return mError; } 415 private: 416 CUSBDevice mDevice; 417 bool mAttached; 418 CVirtualBoxErrorInfo mError; 419 }; 420 421 // 422 // VBoxConsoleCallback class 423 ///////////////////////////////////////////////////////////////////////////// 424 425 class VBoxConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback) 426 { 427 public: 428 429 VBoxConsoleCallback (VBoxConsoleView *v) { 430 #if defined (Q_WS_WIN) 431 mRefCnt = 0; 432 #endif 433 mView = v; 434 } 435 436 virtual ~VBoxConsoleCallback() {} 437 438 NS_DECL_ISUPPORTS 439 440 #if defined (Q_WS_WIN) 441 STDMETHOD_(ULONG, AddRef)() { 442 return ::InterlockedIncrement (&mRefCnt); 443 } 444 STDMETHOD_(ULONG, Release)() 445 { 446 long cnt = ::InterlockedDecrement (&mRefCnt); 447 if (cnt == 0) 448 delete this; 449 return cnt; 450 } 451 #endif 452 VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback) 453 454 STDMETHOD(OnMousePointerShapeChange) (BOOL visible, BOOL alpha, 455 ULONG xhot, ULONG yhot, 456 ULONG width, ULONG height, 457 BYTE *shape) 458 { 459 QApplication::postEvent (mView, 460 new MousePointerChangeEvent (visible, alpha, 461 xhot, yhot, 462 width, height, shape)); 463 return S_OK; 464 } 465 466 STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor) 467 { 468 QApplication::postEvent (mView, 469 new MouseCapabilityEvent (supportsAbsolute, 470 needsHostCursor)); 471 return S_OK; 472 } 473 474 STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock) 475 { 476 QApplication::postEvent (mView, 477 new ModifierKeyChangeEvent (fNumLock, fCapsLock, 478 fScrollLock)); 479 return S_OK; 480 } 481 482 STDMETHOD(OnStateChange)(MachineState_T machineState) 483 { 484 LogFlowFunc (("machineState=%d\n", machineState)); 485 QApplication::postEvent (mView, 486 new StateChangeEvent ((KMachineState) machineState)); 487 return S_OK; 488 } 489 490 STDMETHOD(OnAdditionsStateChange)() 491 { 492 CGuest guest = mView->console().GetGuest(); 493 LogFlowFunc (("ver=%s, active=%d\n", 494 guest.GetAdditionsVersion().toLatin1().constData(), 495 guest.GetAdditionsActive())); 496 QApplication::postEvent (mView, 497 new GuestAdditionsEvent ( 498 guest.GetOSTypeId(), 499 guest.GetAdditionsVersion(), 500 guest.GetAdditionsActive(), 501 guest.GetSupportsSeamless(), 502 guest.GetSupportsGraphics())); 503 return S_OK; 504 } 505 506 STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter) 507 { 508 QApplication::postEvent (mView, 509 new NetworkAdapterChangeEvent (aNetworkAdapter)); 510 return S_OK; 511 } 512 513 STDMETHOD(OnStorageControllerChange) () 514 { 515 /* @todo */ 516 //QApplication::postEvent (mView, 517 // new StorageControllerChangeEvent ()); 518 return S_OK; 519 } 520 521 STDMETHOD(OnMediumChange)(IMediumAttachment *aMediumAttachment) 522 { 523 CMediumAttachment att(aMediumAttachment); 524 switch (att.GetType()) 525 { 526 case KDeviceType_Floppy: 527 QApplication::postEvent(mView, 528 new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy)); 529 break; 530 case KDeviceType_DVD: 531 QApplication::postEvent(mView, 532 new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD)); 533 break; 534 default: 535 /* @todo later add hard disk change as well */ 536 break; 537 } 538 return S_OK; 539 } 540 541 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove) 542 { 543 NOREF(aCPU); 544 NOREF(aRemove); 545 return S_OK; 546 } 547 548 STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort) 549 { 550 NOREF(aSerialPort); 551 return S_OK; 552 } 553 554 STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort) 555 { 556 NOREF(aParallelPort); 557 return S_OK; 558 } 559 560 STDMETHOD(OnVRDPServerChange)() 561 { 562 return S_OK; 563 } 564 565 STDMETHOD(OnRemoteDisplayInfoChange)() 566 { 567 return S_OK; 568 } 569 570 STDMETHOD(OnUSBControllerChange)() 571 { 572 QApplication::postEvent (mView, 573 new USBControllerStateChangeEvent()); 574 return S_OK; 575 } 576 577 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached, 578 IVirtualBoxErrorInfo *aError) 579 { 580 QApplication::postEvent (mView, 581 new USBDeviceStateChangeEvent ( 582 CUSBDevice (aDevice), 583 bool (aAttached), 584 CVirtualBoxErrorInfo (aError))); 585 return S_OK; 586 } 587 588 STDMETHOD(OnSharedFolderChange) (Scope_T aScope) 589 { 590 NOREF(aScope); 591 QApplication::postEvent (mView, 592 new QEvent ((QEvent::Type) 593 VBoxDefs::SharedFolderChangeEventType)); 594 return S_OK; 595 } 596 597 STDMETHOD(OnRuntimeError)(BOOL fatal, IN_BSTR id, IN_BSTR message) 598 { 599 QApplication::postEvent (mView, 600 new RuntimeErrorEvent (!!fatal, 601 QString::fromUtf16 (id), 602 QString::fromUtf16 (message))); 603 return S_OK; 604 } 605 606 STDMETHOD(OnCanShowWindow) (BOOL *canShow) 607 { 608 if (!canShow) 609 return E_POINTER; 610 611 /* as long as there is VBoxConsoleView (which creates/destroys us), it 612 * can be shown */ 613 *canShow = TRUE; 614 return S_OK; 615 } 616 617 STDMETHOD(OnShowWindow) (ULONG64 *winId) 618 { 619 if (!winId) 620 return E_POINTER; 621 622 #if defined (Q_WS_MAC) 623 /* 624 * Let's try the simple approach first - grab the focus. 625 * Getting a window out of the dock (minimized or whatever it's called) 626 * needs to be done on the GUI thread, so post it a note. 627 */ 628 *winId = 0; 629 if (!mView) 630 return S_OK; 631 632 ProcessSerialNumber psn = { 0, kCurrentProcess }; 633 OSErr rc = ::SetFrontProcess (&psn); 634 if (!rc) 635 QApplication::postEvent (mView, new QEvent ((QEvent::Type)VBoxDefs::ShowWindowEventType)); 636 else 637 { 638 /* 639 * It failed for some reason, send the other process our PSN so it can try. 640 * (This is just a precaution should Mac OS X start imposing the same sensible 641 * focus stealing restrictions that other window managers implement.) 642 */ 643 AssertMsgFailed(("SetFrontProcess -> %#x\n", rc)); 644 if (::GetCurrentProcess (&psn)) 645 *winId = RT_MAKE_U64 (psn.lowLongOfPSN, psn.highLongOfPSN); 646 } 647 648 #else 649 /* Return the ID of the top-level console window. */ 650 *winId = (ULONG64) mView->window()->winId(); 651 #endif 652 653 return S_OK; 654 } 655 656 protected: 657 658 VBoxConsoleView *mView; 659 660 #if defined (Q_WS_WIN) 661 private: 662 long mRefCnt; 663 #endif 664 }; 665 666 #if !defined (Q_WS_WIN) 667 NS_DECL_CLASSINFO (VBoxConsoleCallback) 668 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (VBoxConsoleCallback, IConsoleCallback) 669 #endif 670 671 class VBoxViewport: public QWidget 672 { 673 public: 674 VBoxViewport (QWidget *aParent) 675 : QWidget (aParent) 676 { 677 /* No need for background drawing */ 678 setAttribute (Qt::WA_OpaquePaintEvent); 679 } 680 virtual QPaintEngine * paintEngine() const 681 { 682 if (testAttribute (Qt::WA_PaintOnScreen)) 683 return NULL; 684 else 685 return QWidget::paintEngine(); 686 } 687 }; 688 689 // 690 // VBoxConsoleView class 691 ///////////////////////////////////////////////////////////////////////////// 692 693 /** @class VBoxConsoleView 694 * 695 * The VBoxConsoleView class is a widget that implements a console 696 * for the running virtual machine. 697 */ 698 699 VBoxConsoleView::VBoxConsoleView (VBoxConsoleWnd *mainWnd, 700 const CConsole &console, 701 VBoxDefs::RenderMode rm, 702 #ifdef VBOX_WITH_VIDEOHWACCEL 703 bool accelerate2DVideo, 704 #endif 705 QWidget *parent) 706 : QAbstractScrollArea (parent) 707 , mMainWnd (mainWnd) 708 , mConsole (console) 709 , gs (vboxGlobal().settings()) 710 , mAttached (false) 711 , mKbdCaptured (false) 712 , mMouseCaptured (false) 713 , mMouseAbsolute (false) 714 , mMouseIntegration (true) 715 , m_iLastMouseWheelDelta(0) 716 , mDisableAutoCapture (false) 717 , mIsHostkeyPressed (false) 718 , mIsHostkeyAlone (false) 719 , mIgnoreMainwndResize (true) 720 , mAutoresizeGuest (false) 721 , mIgnoreFrameBufferResize (false) 722 , mIgnoreGuestResize (false) 723 , mDoResize (false) 724 , mGuestSupportsGraphics (false) 725 , mNumLock (false) 726 , mScrollLock (false) 727 , mCapsLock (false) 728 , muNumLockAdaptionCnt (2) 729 , muCapsLockAdaptionCnt (2) 730 , mode (rm) 731 #ifdef VBOX_WITH_VIDEOHWACCEL 732 , mAccelerate2DVideo(accelerate2DVideo) 733 #endif 734 #if defined(Q_WS_WIN) 735 , mAlphaCursor (NULL) 736 #endif 737 #if defined(Q_WS_MAC) 738 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA) 739 , mDarwinEventHandlerRef (NULL) 740 # endif 741 , mDarwinKeyModifiers (0) 742 , mKeyboardGrabbed (false) 743 , mDockIconEnabled (true) 744 #endif 745 , mDesktopGeo (DesktopGeo_Invalid) 746 , mPassCAD (false) 747 /* Don't show a hardware pointer until we have one to show */ 748 , mHideHostPointer (true) 749 { 750 Assert (!mConsole.isNull() && 751 !mConsole.GetDisplay().isNull() && 752 !mConsole.GetKeyboard().isNull() && 753 !mConsole.GetMouse().isNull()); 754 755 #ifdef Q_WS_MAC 756 /* Overlay logo for the dock icon */ 757 //mVirtualBoxLogo = ::darwinToCGImageRef ("VirtualBox_cube_42px.png"); 758 QString osTypeId = mConsole.GetGuest().GetOSTypeId(); 759 mDockIconPreview = new VBoxDockIconPreview (mMainWnd, vboxGlobal().vmGuestOSTypeIcon (osTypeId)); 760 761 # ifdef QT_MAC_USE_COCOA 762 /** @todo Carbon -> Cocoa */ 763 # else /* !QT_MAC_USE_COCOA */ 764 /* Install the event handler which will proceed external window handling */ 765 EventHandlerUPP eventHandler = ::NewEventHandlerUPP (::darwinOverlayWindowHandler); 766 EventTypeSpec eventTypes[] = 767 { 768 { kEventClassVBox, kEventVBoxShowWindow }, 769 { kEventClassVBox, kEventVBoxHideWindow }, 770 { kEventClassVBox, kEventVBoxMoveWindow }, 771 { kEventClassVBox, kEventVBoxResizeWindow }, 772 { kEventClassVBox, kEventVBoxDisposeWindow }, 773 { kEventClassVBox, kEventVBoxUpdateDock } 774 }; 775 776 mDarwinWindowOverlayHandlerRef = NULL; 777 ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 778 this, &mDarwinWindowOverlayHandlerRef); 779 ::DisposeEventHandlerUPP (eventHandler); 780 # endif /* !QT_MAC_USE_COCOA */ 781 #endif /* QT_WS_MAC */ 782 783 /* No frame around the view */ 784 setFrameStyle (QFrame::NoFrame); 785 786 #ifdef VBOX_GUI_USE_QGL 787 QWidget *pViewport; 788 switch (mode) 789 { 790 case VBoxDefs::QGLMode: 791 pViewport = new VBoxGLWidget (this, this, NULL); 792 break; 793 default: 794 pViewport = new VBoxViewport (this); 795 } 796 #else 797 VBoxViewport *pViewport = new VBoxViewport (this); 798 #endif 799 setViewport (pViewport); 800 // pViewport->vboxDoInit(); 801 802 /* enable MouseMove events */ 803 viewport()->setMouseTracking (true); 804 805 /* 806 * QScrollView does the below on its own, but let's do it anyway 807 * for the case it will not do it in the future. 808 */ 809 viewport()->installEventFilter (this); 810 811 /* to fix some focus issues */ 812 mMainWnd->menuBar()->installEventFilter (this); 813 814 /* we want to be notified on some parent's events */ 815 mMainWnd->installEventFilter (this); 816 817 #ifdef Q_WS_X11 818 /* initialize the X keyboard subsystem */ 819 initMappedX11Keyboard(QX11Info::display(), 820 vboxGlobal().settings().publicProperty ("GUI/RemapScancodes")); 821 #endif 822 823 ::memset (mPressedKeys, 0, sizeof (mPressedKeys)); 824 825 /* setup rendering */ 826 827 CDisplay display = mConsole.GetDisplay(); 828 Assert (!display.isNull()); 829 830 mFrameBuf = NULL; 831 832 LogFlowFunc (("Rendering mode: %d\n", mode)); 833 834 switch (mode) 835 { 836 #if defined (VBOX_GUI_USE_QGL) 837 case VBoxDefs::QGLMode: 838 mFrameBuf = new VBoxQGLFrameBuffer (this); 839 break; 840 // case VBoxDefs::QGLOverlayMode: 841 // mFrameBuf = new VBoxQGLOverlayFrameBuffer (this); 842 // break; 843 #endif 844 #if defined (VBOX_GUI_USE_QIMAGE) 845 case VBoxDefs::QImageMode: 846 mFrameBuf = 847 #ifdef VBOX_WITH_VIDEOHWACCEL 848 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQImageFrameBuffer> (this, &mainWnd->session()) : 849 #endif 850 new VBoxQImageFrameBuffer (this); 851 break; 852 #endif 853 #if defined (VBOX_GUI_USE_SDL) 854 case VBoxDefs::SDLMode: 855 /* Indicate that we are doing all 856 * drawing stuff ourself */ 857 pViewport->setAttribute (Qt::WA_PaintOnScreen); 858 # ifdef Q_WS_X11 859 /* This is somehow necessary to prevent strange X11 warnings on 860 * i386 and segfaults on x86_64. */ 861 XFlush(QX11Info::display()); 862 # endif 863 mFrameBuf = 864 #if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */ 865 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxSDLFrameBuffer> (this, &mainWnd->session()) : 866 #endif 867 new VBoxSDLFrameBuffer (this); 868 /* 869 * disable scrollbars because we cannot correctly draw in a 870 * scrolled window using SDL 871 */ 872 horizontalScrollBar()->setEnabled (false); 873 verticalScrollBar()->setEnabled (false); 874 break; 875 #endif 876 #if defined (VBOX_GUI_USE_DDRAW) 877 case VBoxDefs::DDRAWMode: 878 mFrameBuf = new VBoxDDRAWFrameBuffer (this); 879 break; 880 #endif 881 #if defined (VBOX_GUI_USE_QUARTZ2D) 882 case VBoxDefs::Quartz2DMode: 883 /* Indicate that we are doing all 884 * drawing stuff ourself */ 885 pViewport->setAttribute (Qt::WA_PaintOnScreen); 886 mFrameBuf = 887 #ifdef VBOX_WITH_VIDEOHWACCEL 888 mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer> (this, &mainWnd->session()) : 889 #endif 890 new VBoxQuartz2DFrameBuffer (this); 891 break; 892 #endif 893 default: 894 AssertReleaseMsgFailed (("Render mode must be valid: %d\n", mode)); 895 LogRel (("Invalid render mode: %d\n", mode)); 896 qApp->exit (1); 897 break; 898 } 899 900 #if defined (VBOX_GUI_USE_DDRAW) 901 if (!mFrameBuf || mFrameBuf->address() == NULL) 902 { 903 if (mFrameBuf) 904 delete mFrameBuf; 905 mode = VBoxDefs::QImageMode; 906 mFrameBuf = new VBoxQImageFrameBuffer (this); 907 } 908 #endif 909 910 if (mFrameBuf) 911 { 912 mFrameBuf->AddRef(); 913 display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer (mFrameBuf)); 914 } 915 916 /* setup the callback */ 917 mCallback = CConsoleCallback (new VBoxConsoleCallback (this)); 918 mConsole.RegisterCallback (mCallback); 919 AssertWrapperOk (mConsole); 920 921 QPalette palette (viewport()->palette()); 922 palette.setColor (viewport()->backgroundRole(), Qt::black); 923 viewport()->setPalette (palette); 924 925 setSizePolicy (QSizePolicy (QSizePolicy::Maximum, QSizePolicy::Maximum)); 926 setMaximumSize (sizeHint()); 927 928 setFocusPolicy (Qt::WheelFocus); 929 930 /* Remember the desktop geometry and register for geometry change 931 events for telling the guest about video modes we like. */ 932 933 QString desktopGeometry = vboxGlobal().settings() 934 .publicProperty ("GUI/MaxGuestResolution"); 935 if ((desktopGeometry == QString::null) || 936 (desktopGeometry == "auto")) 937 setDesktopGeometry (DesktopGeo_Automatic, 0, 0); 938 else if (desktopGeometry == "any") 939 setDesktopGeometry (DesktopGeo_Any, 0, 0); 940 else 941 { 942 int width = desktopGeometry.section (',', 0, 0).toInt(); 943 int height = desktopGeometry.section (',', 1, 1).toInt(); 944 setDesktopGeometry (DesktopGeo_Fixed, width, height); 945 } 946 connect (QApplication::desktop(), SIGNAL (resized (int)), 947 this, SLOT (doResizeDesktop (int))); 948 949 QString passCAD = mConsole.GetMachine().GetExtraData (VBoxDefs::GUI_PassCAD); 950 if (!passCAD.isEmpty() && 951 ((passCAD != "false") || (passCAD != "no")) 952 ) 953 mPassCAD = true; 954 955 #if defined (Q_WS_WIN) 956 gView = this; 957 #endif 958 959 #if defined (Q_WS_PM) 960 bool ok = VBoxHlpInstallKbdHook (0, winId(), UM_PREACCEL_CHAR); 961 Assert (ok); 962 NOREF (ok); 963 #endif 964 } 965 966 VBoxConsoleView::~VBoxConsoleView() 967 { 968 #if defined (Q_WS_PM) 969 bool ok = VBoxHlpUninstallKbdHook (0, winId(), UM_PREACCEL_CHAR); 970 Assert (ok); 971 NOREF (ok); 972 #endif 973 974 #if defined (Q_WS_WIN) 975 if (gKbdHook) 976 UnhookWindowsHookEx (gKbdHook); 977 gView = 0; 978 if (mAlphaCursor) 979 DestroyIcon (mAlphaCursor); 980 #endif 981 982 if (mFrameBuf) 983 { 984 /* detach our framebuffer from Display */ 985 CDisplay display = mConsole.GetDisplay(); 986 Assert (!display.isNull()); 987 display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL)); 988 /* release the reference */ 989 mFrameBuf->Release(); 990 mFrameBuf = NULL; 991 } 992 993 mConsole.UnregisterCallback (mCallback); 994 995 #if defined (Q_WS_MAC) 996 # if !defined (QT_MAC_USE_COCOA) 997 if (mDarwinWindowOverlayHandlerRef) 998 { 999 ::RemoveEventHandler (mDarwinWindowOverlayHandlerRef); 1000 mDarwinWindowOverlayHandlerRef = NULL; 1001 } 1002 # endif 1003 delete mDockIconPreview; 1004 mDockIconPreview = NULL; 1005 #endif 1006 } 1007 1008 // 1009 // Public members 1010 ///////////////////////////////////////////////////////////////////////////// 1011 1012 QSize VBoxConsoleView::sizeHint() const 1013 { 1014 #ifdef VBOX_WITH_DEBUGGER /** @todo figure out a more proper fix. */ 1015 /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done 1016 * by DevVGA if provoked before power on. */ 1017 QSize fb(mFrameBuf->width(), mFrameBuf->height()); 1018 if ( ( fb.width() < 16 1019 || fb.height() < 16) 1020 && ( vboxGlobal().isStartPausedEnabled() 1021 || vboxGlobal().isDebuggerAutoShowEnabled()) ) 1022 fb = QSize(640, 480); 1023 return QSize (fb.width() + frameWidth() * 2, 1024 fb.height() + frameWidth() * 2); 1025 #else 1026 return QSize (mFrameBuf->width() + frameWidth() * 2, 1027 mFrameBuf->height() + frameWidth() * 2); 1028 #endif 1029 } 1030 1031 /** 1032 * Attaches this console view to the managed virtual machine. 1033 * 1034 * @note This method is not really necessary these days -- the only place where 1035 * it gets called is VBoxConsole::openView(), right after powering the 1036 * VM up. We leave it as is just in case attaching/detaching will become 1037 * necessary some day (there are useful attached checks everywhere in the 1038 * code). 1039 */ 1040 void VBoxConsoleView::attach() 1041 { 1042 if (!mAttached) 1043 { 1044 mAttached = true; 1045 } 1046 } 1047 1048 /** 1049 * Detaches this console view from the VM. Must be called to indicate 1050 * that the virtual machine managed by this instance will be no more valid 1051 * after this call. 1052 * 1053 * @note This method is not really necessary these days -- the only place where 1054 * it gets called is VBoxConsole::closeView(), when the VM is powered 1055 * down, before deleting VBoxConsoleView. We leave it as is just in case 1056 * attaching/detaching will become necessary some day (there are useful 1057 * attached checks everywhere in the code). 1058 */ 1059 void VBoxConsoleView::detach() 1060 { 1061 if (mAttached) 1062 { 1063 /* reuse the focus event handler to uncapture everything */ 1064 focusEvent (false); 1065 mAttached = false; 1066 } 1067 } 1068 1069 /** 1070 * Resizes the toplevel widget to fit the console view w/o scrollbars. 1071 * If adjustPosition is true and such resize is not possible (because the 1072 * console view size is lagrer then the available screen space) the toplevel 1073 * widget is resized and moved to become as large as possible while staying 1074 * fully visible. 1075 */ 1076 void VBoxConsoleView::normalizeGeometry (bool adjustPosition /* = false */) 1077 { 1078 /* Make no normalizeGeometry in case we are in manual resize 1079 * mode or main window is maximized */ 1080 if (mMainWnd->isWindowMaximized() || mMainWnd->isWindowFullScreen()) 58 /* Make no normalizeGeometry in case we are in manual resize mode or main window is maximized */ 59 if (machineWindowWrapper()->machineWindow()->isMaximized()) 1081 60 return; 1082 61 1083 QWidget * tlw= window();62 QWidget *pTopLevelWidget = window(); 1084 63 1085 64 /* calculate client window offsets */ 1086 QRect fr = tlw->frameGeometry();1087 QRect r = tlw->geometry();65 QRect fr = pTopLevelWidget->frameGeometry(); 66 QRect r = pTopLevelWidget->geometry(); 1088 67 int dl = r.left() - fr.left(); 1089 68 int dt = r.top() - fr.top(); … … 1092 71 1093 72 /* get the best size w/o scroll bars */ 1094 QSize s = tlw->sizeHint();73 QSize s = pTopLevelWidget->sizeHint(); 1095 74 1096 75 /* resize the frame to fit the contents */ 1097 s -= tlw->size();1098 fr.setRight 1099 fr.setBottom 76 s -= pTopLevelWidget->size(); 77 fr.setRight(fr.right() + s.width()); 78 fr.setBottom(fr.bottom() + s.height()); 1100 79 1101 if ( adjustPosition)80 if (bAdjustPosition) 1102 81 { 1103 82 QRegion ar; … … 1106 85 /* Compose complex available region */ 1107 86 for (int i = 0; i < dwt->numScreens(); ++ i) 1108 ar += dwt->availableGeometry 87 ar += dwt->availableGeometry(i); 1109 88 else 1110 89 /* Get just a simple available rectangle */ 1111 ar = dwt->availableGeometry (tlw->pos());90 ar = dwt->availableGeometry(pTopLevelWidget->pos()); 1112 91 1113 fr = VBoxGlobal::normalizeGeometry ( 1114 fr, ar, mode != VBoxDefs::SDLMode /* canResize */); 92 fr = VBoxGlobal::normalizeGeometry(fr, ar, mode != VBoxDefs::SDLMode /* canResize */); 1115 93 } 1116 94 1117 95 #if 0 1118 /* center the frame on the desktop*/1119 fr.moveCenter 96 /* Center the frame on the desktop: */ 97 fr.moveCenter(ar.center()); 1120 98 #endif 1121 99 1122 /* finally, set the frame geometry */ 1123 tlw->setGeometry (fr.left() + dl, fr.top() + dt, 1124 fr.width() - dl - dr, fr.height() - dt - db); 100 /* Finally, set the frame geometry */ 101 pTopLevelWidget->setGeometry(fr.left() + dl, fr.top() + dt, fr.width() - dl - dr, fr.height() - dt - db); 1125 102 } 1126 103 1127 /** 1128 * Pauses or resumes the VM execution. 1129 */ 1130 bool VBoxConsoleView::pause (bool on) 104 void UIMachineViewNormal::maybeRestrictMinimumSize() 1131 105 { 1132 /* QAction::setOn() emits the toggled() signal, so avoid recursion when 1133 * QAction::setOn() is called from VBoxConsoleWnd::updateMachineState() */ 1134 if (isPaused() == on) 1135 return true; 1136 1137 if (on) 1138 mConsole.Pause(); 1139 else 1140 mConsole.Resume(); 1141 1142 bool ok = mConsole.isOk(); 1143 if (!ok) 106 /* Sets the minimum size restriction depending on the auto-resize feature state and the current rendering mode. 107 * Currently, the restriction is set only in SDL mode and only when the auto-resize feature is inactive. 108 * We need to do that because we cannot correctly draw in a scrolled window in SDL mode. 109 * In all other modes, or when auto-resize is in force, this function does nothing. */ 110 if (mode == VBoxDefs::SDLMode) 1144 111 { 1145 if ( on)1146 vboxProblem().cannotPauseMachine (mConsole);112 if (!m_bIsGuestSupportsGraphics || !m_bIsGuestAutoresizeEnabled) 113 setMinimumSize(sizeHint()); 1147 114 else 1148 vboxProblem().cannotResumeMachine (mConsole); 1149 } 1150 1151 return ok; 1152 } 1153 1154 /** 1155 * Temporarily disables the mouse integration (or enables it back). 1156 */ 1157 void VBoxConsoleView::setMouseIntegrationEnabled (bool enabled) 1158 { 1159 if (mMouseIntegration == enabled) 1160 return; 1161 1162 if (mMouseAbsolute) 1163 captureMouse (!enabled, false); 1164 1165 /* Hiding host cursor in case we are entering mouse integration 1166 * mode until it's shape is set to the guest cursor shape in 1167 * OnMousePointerShapeChange event handler. 1168 * 1169 * This is necessary to avoid double-cursor issues where both the 1170 * guest and the host cursors are displayed in one place, one above the 1171 * other. 1172 * 1173 * This is a workaround because the correct decision would be to notify 1174 * the Guest Additions about we are entering the mouse integration 1175 * mode. The GuestOS should hide it's cursor to allow using of 1176 * host cursor for the guest's manipulation. 1177 * 1178 * This notification is not always possible though, as not all guests 1179 * support switching to a hardware pointer on demand. */ 1180 if (enabled) 1181 viewport()->setCursor (QCursor (Qt::BlankCursor)); 1182 1183 mMouseIntegration = enabled; 1184 1185 emitMouseStateChanged(); 1186 } 1187 1188 void VBoxConsoleView::setAutoresizeGuest (bool on) 1189 { 1190 if (mAutoresizeGuest != on) 1191 { 1192 mAutoresizeGuest = on; 1193 1194 maybeRestrictMinimumSize(); 1195 1196 if (mGuestSupportsGraphics && mAutoresizeGuest) 1197 doResizeHint(); 115 setMinimumSize(0, 0); 1198 116 } 1199 117 } 1200 118 1201 /** 1202 * This method is called by VBoxConsoleWnd after it does everything necessary 1203 * on its side to go to or from fullscreen, but before it is shown. 1204 */ 1205 void VBoxConsoleView::onFullscreenChange (bool /* on */) 119 void UIMachineViewNormal::doResizeHint(const QSize & /*toSize*/) 1206 120 { 1207 /* Nothing to do here so far */ 1208 } 1209 1210 /** 1211 * Notify the console scroll-view about the console-window is opened. 1212 */ 1213 void VBoxConsoleView::onViewOpened() 1214 { 1215 /* Variable mIgnoreMainwndResize was initially "true" to ignore QT 1216 * initial resize event in case of auto-resize feature is on. 1217 * Currently, initial resize event is already processed, so we set 1218 * mIgnoreMainwndResize to "false" to process all further resize 1219 * events as user-initiated window resize events. */ 1220 mIgnoreMainwndResize = false; 1221 } 1222 1223 // 1224 // Protected Events 1225 ///////////////////////////////////////////////////////////////////////////// 1226 1227 bool VBoxConsoleView::event (QEvent *e) 1228 { 1229 if (mAttached) 1230 { 1231 switch (e->type()) 1232 { 1233 case QEvent::FocusIn: 1234 { 1235 if (isRunning()) 1236 focusEvent (true); 1237 break; 1238 } 1239 case QEvent::FocusOut: 1240 { 1241 if (isRunning()) 1242 focusEvent (false); 1243 else 1244 { 1245 /* release the host key and all other pressed keys too even 1246 * when paused (otherwise, we will get stuck keys in the 1247 * guest when doing sendChangedKeyStates() on resume because 1248 * key presses were already recorded in mPressedKeys but key 1249 * releases will most likely not reach us but the new focus 1250 * window instead). */ 1251 releaseAllPressedKeys (true /* aReleaseHostKey */); 1252 } 1253 break; 1254 } 1255 1256 case VBoxDefs::ResizeEventType: 1257 { 1258 /* Some situations require initial VGA Resize Request 1259 * to be ignored at all, leaving previous framebuffer, 1260 * console widget and vm window size preserved. */ 1261 if (mIgnoreGuestResize) 1262 return true; 1263 1264 bool oldIgnoreMainwndResize = mIgnoreMainwndResize; 1265 mIgnoreMainwndResize = true; 1266 1267 VBoxResizeEvent *re = (VBoxResizeEvent *) e; 1268 LogFlow (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n", 1269 re->width(), re->height(), re->bitsPerPixel())); 1270 #ifdef DEBUG_michael 1271 LogRel (("Resize event from guest: %d x %d x %d bpp\n", 1272 re->width(), re->height(), re->bitsPerPixel())); 1273 #endif 1274 1275 /* Store the new size to prevent unwanted resize hints being 1276 * sent back. */ 1277 storeConsoleSize(re->width(), re->height()); 1278 /* do frame buffer dependent resize */ 1279 1280 /* restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen 1281 * widgets are present. This is the case on linux with SDL. As 1282 * workaround we save/restore the arrow cursor manually. See 1283 * http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry 1284 * for details. 1285 * 1286 * Moreover the current cursor, which could be set by the guest, 1287 * should be restored after resize. 1288 */ 1289 QCursor cursor; 1290 if (shouldHideHostPointer()) 1291 cursor = QCursor (Qt::BlankCursor); 1292 else 1293 cursor = viewport()->cursor(); 1294 mFrameBuf->resizeEvent (re); 1295 viewport()->setCursor (cursor); 1296 1297 #ifdef Q_WS_MAC 1298 mDockIconPreview->setOriginalSize (re->width(), re->height()); 1299 #endif /* Q_WS_MAC */ 1300 1301 /* This event appears in case of guest video was changed 1302 * for somehow even without video resolution change. 1303 * In this last case the host VM window will not be resized 1304 * according this event and the host mouse cursor which was 1305 * unset to default here will not be hidden in capture state. 1306 * So it is necessary to perform updateMouseClipping() for 1307 * the guest resize event if the mouse cursor was captured. */ 1308 if (mMouseCaptured) 1309 updateMouseClipping(); 1310 1311 /* apply maximum size restriction */ 1312 setMaximumSize (sizeHint()); 1313 1314 maybeRestrictMinimumSize(); 1315 1316 /* resize the guest canvas */ 1317 if (!mIgnoreFrameBufferResize) 1318 resize (re->width(), re->height()); 1319 updateSliders(); 1320 /* Let our toplevel widget calculate its sizeHint properly. */ 1321 #ifdef Q_WS_X11 1322 /* We use processEvents rather than sendPostedEvents & set the 1323 * time out value to max cause on X11 otherwise the layout 1324 * isn't calculated correctly. Dosn't find the bug in Qt, but 1325 * this could be triggered through the async nature of the X11 1326 * window event system. */ 1327 QCoreApplication::processEvents (QEventLoop::AllEvents, INT_MAX); 1328 #else /* Q_WS_X11 */ 1329 QCoreApplication::sendPostedEvents (0, QEvent::LayoutRequest); 1330 #endif /* Q_WS_X11 */ 1331 1332 if (!mIgnoreFrameBufferResize) 1333 normalizeGeometry (true /* adjustPosition */); 1334 1335 /* report to the VM thread that we finished resizing */ 1336 mConsole.GetDisplay().ResizeCompleted (0); 1337 1338 mIgnoreMainwndResize = oldIgnoreMainwndResize; 1339 1340 /* update geometry after entering fullscreen | seamless */ 1341 if (mMainWnd->isTrueFullscreen() || mMainWnd->isTrueSeamless()) 1342 updateGeometry(); 1343 1344 /* make sure that all posted signals are processed */ 1345 qApp->processEvents(); 1346 1347 /* emit a signal about guest was resized */ 1348 emit resizeHintDone(); 1349 1350 /* We also recalculate the desktop geometry if this is determined 1351 * automatically. In fact, we only need this on the first resize, 1352 * but it is done every time to keep the code simpler. */ 1353 calculateDesktopGeometry(); 1354 1355 /* Enable frame-buffer resize watching. */ 1356 if (mIgnoreFrameBufferResize) 1357 { 1358 mIgnoreFrameBufferResize = false; 1359 } 1360 1361 mMainWnd->onDisplayResize (re->width(), re->height()); 1362 1363 return true; 1364 } 1365 1366 /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(). */ 1367 case VBoxDefs::RepaintEventType: 1368 { 1369 VBoxRepaintEvent *re = (VBoxRepaintEvent *) e; 1370 viewport()->repaint (re->x() - contentsX(), 1371 re->y() - contentsY(), 1372 re->width(), re->height()); 1373 /* mConsole.GetDisplay().UpdateCompleted(); - the event was acked already */ 1374 return true; 1375 } 1376 1377 #ifdef VBOX_WITH_VIDEOHWACCEL 1378 case VBoxDefs::VHWACommandProcessType: 1379 { 1380 mFrameBuf->doProcessVHWACommand(e); 1381 return true; 1382 } 1383 #endif 1384 1385 case VBoxDefs::SetRegionEventType: 1386 { 1387 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e; 1388 if (mMainWnd->isTrueSeamless() && 1389 sre->region() != mLastVisibleRegion) 1390 { 1391 mLastVisibleRegion = sre->region(); 1392 mMainWnd->setMask (sre->region()); 1393 } 1394 else if (!mLastVisibleRegion.isEmpty() && 1395 !mMainWnd->isTrueSeamless()) 1396 mLastVisibleRegion = QRegion(); 1397 return true; 1398 } 1399 1400 case VBoxDefs::MousePointerChangeEventType: 1401 { 1402 MousePointerChangeEvent *me = (MousePointerChangeEvent *) e; 1403 /* change cursor shape only when mouse integration is 1404 * supported (change mouse shape type event may arrive after 1405 * mouse capability change that disables integration */ 1406 if (mMouseAbsolute) 1407 setPointerShape (me); 1408 else 1409 /* Note: actually we should still remember the requested 1410 * cursor shape. If we can't do that, at least remember 1411 * the requested visiblilty. */ 1412 mHideHostPointer = !me->isVisible(); 1413 return true; 1414 } 1415 case VBoxDefs::MouseCapabilityEventType: 1416 { 1417 MouseCapabilityEvent *me = (MouseCapabilityEvent *) e; 1418 if (mMouseAbsolute != me->supportsAbsolute()) 1419 { 1420 mMouseAbsolute = me->supportsAbsolute(); 1421 /* correct the mouse capture state and reset the cursor 1422 * to the default shape if necessary */ 1423 if (mMouseAbsolute) 1424 { 1425 CMouse mouse = mConsole.GetMouse(); 1426 mouse.PutMouseEventAbsolute (-1, -1, 0, 1427 0 /* Horizontal wheel */, 1428 0); 1429 captureMouse (false, false); 1430 } 1431 else 1432 viewport()->unsetCursor(); 1433 emitMouseStateChanged(); 1434 vboxProblem().remindAboutMouseIntegration (mMouseAbsolute); 1435 } 1436 if (me->needsHostCursor()) 1437 mMainWnd->setMouseIntegrationLocked (false); 1438 else 1439 mMainWnd->setMouseIntegrationLocked (true); 1440 return true; 1441 } 1442 1443 case VBoxDefs::ModifierKeyChangeEventType: 1444 { 1445 ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )e; 1446 if (me->numLock() != mNumLock) 1447 muNumLockAdaptionCnt = 2; 1448 if (me->capsLock() != mCapsLock) 1449 muCapsLockAdaptionCnt = 2; 1450 mNumLock = me->numLock(); 1451 mCapsLock = me->capsLock(); 1452 mScrollLock = me->scrollLock(); 1453 return true; 1454 } 1455 1456 case VBoxDefs::MachineStateChangeEventType: 1457 { 1458 StateChangeEvent *me = (StateChangeEvent *) e; 1459 LogFlowFunc (("MachineStateChangeEventType: state=%d\n", 1460 me->machineState())); 1461 onStateChange (me->machineState()); 1462 emit machineStateChanged (me->machineState()); 1463 return true; 1464 } 1465 1466 case VBoxDefs::AdditionsStateChangeEventType: 1467 { 1468 GuestAdditionsEvent *ge = (GuestAdditionsEvent *) e; 1469 LogFlowFunc (("AdditionsStateChangeEventType\n")); 1470 1471 /* Always send a size hint if we are in fullscreen or seamless 1472 * when the graphics capability is enabled, in case the host 1473 * resolution has changed since the VM was last run. */ 1474 #if 0 1475 if (!mDoResize && !mGuestSupportsGraphics && 1476 ge->supportsGraphics() && 1477 (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen())) 1478 mDoResize = true; 1479 #endif 1480 1481 mGuestSupportsGraphics = ge->supportsGraphics(); 1482 1483 maybeRestrictMinimumSize(); 1484 1485 #if 0 1486 /* This will only be acted upon if mDoResize is true. */ 1487 doResizeHint(); 1488 #endif 1489 1490 emit additionsStateChanged (ge->additionVersion(), 1491 ge->additionActive(), 1492 ge->supportsSeamless(), 1493 ge->supportsGraphics()); 1494 return true; 1495 } 1496 1497 case VBoxDefs::MediaDriveChangeEventType: 1498 { 1499 MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) e; 1500 LogFlowFunc (("MediaChangeEvent\n")); 1501 1502 emit mediaDriveChanged (mce->type()); 1503 return true; 1504 } 1505 1506 case VBoxDefs::ActivateMenuEventType: 1507 { 1508 ActivateMenuEvent *ame = (ActivateMenuEvent *) e; 1509 ame->action()->trigger(); 1510 1511 /* 1512 * The main window and its children can be destroyed at this 1513 * point (if, for example, the activated menu item closes the 1514 * main window). Detect this situation to prevent calls to 1515 * destroyed widgets. 1516 */ 1517 QWidgetList list = QApplication::topLevelWidgets(); 1518 bool destroyed = list.indexOf (mMainWnd) < 0; 1519 if (!destroyed && mMainWnd->statusBar()) 1520 mMainWnd->statusBar()->clearMessage(); 1521 1522 return true; 1523 } 1524 1525 case VBoxDefs::NetworkAdapterChangeEventType: 1526 { 1527 /* no specific adapter information stored in this 1528 * event is currently used */ 1529 emit networkStateChange(); 1530 return true; 1531 } 1532 1533 case VBoxDefs::USBCtlStateChangeEventType: 1534 { 1535 emit usbStateChange(); 1536 return true; 1537 } 1538 1539 case VBoxDefs::USBDeviceStateChangeEventType: 1540 { 1541 USBDeviceStateChangeEvent *ue = (USBDeviceStateChangeEvent *)e; 1542 1543 bool success = ue->error().isNull(); 1544 1545 if (!success) 1546 { 1547 if (ue->attached()) 1548 vboxProblem().cannotAttachUSBDevice ( 1549 mConsole, 1550 vboxGlobal().details (ue->device()), ue->error()); 1551 else 1552 vboxProblem().cannotDetachUSBDevice ( 1553 mConsole, 1554 vboxGlobal().details (ue->device()), ue->error()); 1555 } 1556 1557 emit usbStateChange(); 1558 1559 return true; 1560 } 1561 1562 case VBoxDefs::SharedFolderChangeEventType: 1563 { 1564 emit sharedFoldersChanged(); 1565 return true; 1566 } 1567 1568 case VBoxDefs::RuntimeErrorEventType: 1569 { 1570 RuntimeErrorEvent *ee = (RuntimeErrorEvent *) e; 1571 vboxProblem().showRuntimeError (mConsole, ee->fatal(), 1572 ee->errorID(), ee->message()); 1573 return true; 1574 } 1575 1576 case QEvent::KeyPress: 1577 case QEvent::KeyRelease: 1578 { 1579 QKeyEvent *ke = (QKeyEvent *) e; 1580 1581 #ifdef Q_WS_PM 1582 /// @todo temporary solution to send Alt+Tab and friends to 1583 // the guest. The proper solution is to write a keyboard 1584 // driver that will steal these combos from the host (it's 1585 // impossible to do so using hooks on OS/2). 1586 1587 if (mIsHostkeyPressed) 1588 { 1589 bool pressed = e->type() == QEvent::KeyPress; 1590 CKeyboard keyboard = mConsole.GetKeyboard(); 1591 1592 /* whether the host key is Shift so that it will modify 1593 * the hot key values? Note that we don't distinguish 1594 * between left and right shift here (too much hassle) */ 1595 const bool kShift = (gs.hostKey() == VK_SHIFT || 1596 gs.hostKey() == VK_LSHIFT) && 1597 (ke->state() & Qt::ShiftModifier); 1598 /* define hot keys according to the Shift state */ 1599 const int kAltTab = kShift ? Qt::Key_Exclam : Qt::Key_1; 1600 const int kAltShiftTab = kShift ? Qt::Key_At : Qt::Key_2; 1601 const int kCtrlEsc = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft; 1602 1603 /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */ 1604 if (ke->key() == kAltTab || ke->key() == kAltShiftTab) 1605 { 1606 if (pressed) 1607 { 1608 /* Send the Alt press to the guest */ 1609 if (!(mPressedKeysCopy [0x38] & IsKeyPressed)) 1610 { 1611 /* store the press in *Copy to have it automatically 1612 * released when the Host key is released */ 1613 mPressedKeysCopy [0x38] |= IsKeyPressed; 1614 keyboard.PutScancode (0x38); 1615 } 1616 1617 /* Make sure Shift is pressed if it's Key_2 and released 1618 * if it's Key_1 */ 1619 if (ke->key() == kAltTab && 1620 (mPressedKeysCopy [0x2A] & IsKeyPressed)) 1621 { 1622 mPressedKeysCopy [0x2A] &= ~IsKeyPressed; 1623 keyboard.PutScancode (0xAA); 1624 } 1625 else 1626 if (ke->key() == kAltShiftTab && 1627 !(mPressedKeysCopy [0x2A] & IsKeyPressed)) 1628 { 1629 mPressedKeysCopy [0x2A] |= IsKeyPressed; 1630 keyboard.PutScancode (0x2A); 1631 } 1632 } 1633 1634 keyboard.PutScancode (pressed ? 0x0F : 0x8F); 1635 1636 ke->accept(); 1637 return true; 1638 } 1639 1640 /* Simulate Ctrl+Esc on Host+Tilde */ 1641 if (ke->key() == kCtrlEsc) 1642 { 1643 /* Send the Ctrl press to the guest */ 1644 if (pressed && !(mPressedKeysCopy [0x1d] & IsKeyPressed)) 1645 { 1646 /* store the press in *Copy to have it automatically 1647 * released when the Host key is released */ 1648 mPressedKeysCopy [0x1d] |= IsKeyPressed; 1649 keyboard.PutScancode (0x1d); 1650 } 1651 1652 keyboard.PutScancode (pressed ? 0x01 : 0x81); 1653 1654 ke->accept(); 1655 return true; 1656 } 1657 } 1658 1659 /* fall through to normal processing */ 1660 1661 #endif /* Q_WS_PM */ 1662 1663 if (mIsHostkeyPressed && e->type() == QEvent::KeyPress) 1664 { 1665 if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12) 1666 { 1667 QVector <LONG> combo (6); 1668 combo [0] = 0x1d; /* Ctrl down */ 1669 combo [1] = 0x38; /* Alt down */ 1670 combo [4] = 0xb8; /* Alt up */ 1671 combo [5] = 0x9d; /* Ctrl up */ 1672 if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F10) 1673 { 1674 combo [2] = 0x3b + (ke->key() - Qt::Key_F1); /* F1-F10 down */ 1675 combo [3] = 0xbb + (ke->key() - Qt::Key_F1); /* F1-F10 up */ 1676 } 1677 /* some scan slice */ 1678 else if (ke->key() >= Qt::Key_F11 && ke->key() <= Qt::Key_F12) 1679 { 1680 combo [2] = 0x57 + (ke->key() - Qt::Key_F11); /* F11-F12 down */ 1681 combo [3] = 0xd7 + (ke->key() - Qt::Key_F11); /* F11-F12 up */ 1682 } 1683 else 1684 Assert (0); 1685 1686 CKeyboard keyboard = mConsole.GetKeyboard(); 1687 keyboard.PutScancodes (combo); 1688 } 1689 else if (ke->key() == Qt::Key_Home) 1690 { 1691 /* Activate the main menu */ 1692 if (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen()) 1693 mMainWnd->popupMainMenu (mMouseCaptured); 1694 else 1695 { 1696 /* In Qt4 it is not enough to just set the focus to 1697 * menu-bar. So to get the menu-bar we have to send 1698 * Qt::Key_Alt press/release events directly. */ 1699 QKeyEvent e1 (QEvent::KeyPress, Qt::Key_Alt, 1700 Qt::NoModifier); 1701 QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt, 1702 Qt::NoModifier); 1703 QApplication::sendEvent (mMainWnd->menuBar(), &e1); 1704 QApplication::sendEvent (mMainWnd->menuBar(), &e2); 1705 } 1706 } 1707 else 1708 { 1709 /* process hot keys not processed in keyEvent() 1710 * (as in case of non-alphanumeric keys) */ 1711 processHotKey (QKeySequence (ke->key()), 1712 mMainWnd->menuBar()->actions()); 1713 } 1714 } 1715 else if (!mIsHostkeyPressed && e->type() == QEvent::KeyRelease) 1716 { 1717 /* Show a possible warning on key release which seems to 1718 * be more expected by the end user */ 1719 1720 if (isPaused()) 1721 { 1722 /* if the reminder is disabled we pass the event to 1723 * Qt to enable normal keyboard functionality 1724 * (for example, menu access with Alt+Letter) */ 1725 if (!vboxProblem().remindAboutPausedVMInput()) 1726 break; 1727 } 1728 } 1729 1730 ke->accept(); 1731 return true; 1732 } 1733 1734 #ifdef Q_WS_MAC 1735 /* posted OnShowWindow */ 1736 case VBoxDefs::ShowWindowEventType: 1737 { 1738 /* 1739 * Dunno what Qt3 thinks a window that has minimized to the dock 1740 * should be - it is not hidden, neither is it minimized. OTOH it is 1741 * marked shown and visible, but not activated. This latter isn't of 1742 * much help though, since at this point nothing is marked activated. 1743 * I might have overlooked something, but I'm buggered what if I know 1744 * what. So, I'll just always show & activate the stupid window to 1745 * make it get out of the dock when the user wishes to show a VM. 1746 */ 1747 window()->show(); 1748 window()->activateWindow(); 1749 return true; 1750 } 1751 #endif 1752 default: 1753 break; 1754 } 1755 } 1756 1757 return QAbstractScrollArea::event (e); 1758 } 1759 1760 #ifdef VBOX_WITH_VIDEOHWACCEL 1761 void VBoxConsoleView::scrollContentsBy (int dx, int dy) 1762 { 1763 if (mAttached && mFrameBuf) 1764 { 1765 mFrameBuf->viewportScrolled(dx, dy); 1766 } 1767 QAbstractScrollArea::scrollContentsBy (dx, dy); 1768 } 1769 #endif 1770 1771 1772 bool VBoxConsoleView::eventFilter (QObject *watched, QEvent *e) 1773 { 1774 if (mAttached && watched == viewport()) 1775 { 1776 switch (e->type()) 1777 { 1778 case QEvent::MouseMove: 1779 case QEvent::MouseButtonPress: 1780 case QEvent::MouseButtonDblClick: 1781 case QEvent::MouseButtonRelease: 1782 { 1783 QMouseEvent *me = (QMouseEvent *) e; 1784 m_iLastMouseWheelDelta = 0; 1785 if (mouseEvent (me->type(), me->pos(), me->globalPos(), 1786 me->buttons(), me->modifiers(), 1787 0, Qt::Horizontal)) 1788 return true; /* stop further event handling */ 1789 break; 1790 } 1791 case QEvent::Wheel: 1792 { 1793 QWheelEvent *we = (QWheelEvent *) e; 1794 /* There are pointing devices which send smaller values for the 1795 * delta than 120. Here we sum them up until we are greater 1796 * than 120. This allows to have finer control over the speed 1797 * acceleration & enables such devices to send a valid wheel 1798 * event to our guest mouse device at all. */ 1799 int iDelta = 0; 1800 m_iLastMouseWheelDelta += we->delta(); 1801 if (qAbs(m_iLastMouseWheelDelta) >= 120) 1802 { 1803 iDelta = m_iLastMouseWheelDelta; 1804 m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120; 1805 } 1806 if (mouseEvent (we->type(), we->pos(), we->globalPos(), 1807 #ifdef QT_MAC_USE_COCOA 1808 /* Qt Cocoa is buggy. It always reports a left 1809 * button pressed when the mouse wheel event 1810 * occurs. A workaround is to ask the 1811 * application which buttons are pressed 1812 * currently. */ 1813 QApplication::mouseButtons(), 1814 #else /* QT_MAC_USE_COCOA */ 1815 we->buttons(), 1816 #endif /* QT_MAC_USE_COCOA */ 1817 we->modifiers(), 1818 iDelta, we->orientation())) 1819 return true; /* stop further event handling */ 1820 break; 1821 } 1822 #ifdef Q_WS_MAC 1823 case QEvent::Leave: 1824 { 1825 /* Enable mouse event compression if we leave the VM view. This 1826 is necessary for having smooth resizing of the VM/other 1827 windows. */ 1828 setMouseCoalescingEnabled (true); 1829 break; 1830 } 1831 case QEvent::Enter: 1832 { 1833 /* Disable mouse event compression if we enter the VM view. So 1834 all mouse events are registered in the VM. Only do this if 1835 the keyboard/mouse is grabbed (this is when we have a valid 1836 event handler). */ 1837 setMouseCoalescingEnabled (false); 1838 break; 1839 } 1840 #endif /* Q_WS_MAC */ 1841 case QEvent::Resize: 1842 { 1843 if (mMouseCaptured) 1844 updateMouseClipping(); 1845 #ifdef VBOX_WITH_VIDEOHWACCEL 1846 if (mFrameBuf) 1847 { 1848 mFrameBuf->viewportResized((QResizeEvent*)e); 1849 } 1850 #endif 1851 break; 1852 } 1853 default: 1854 break; 1855 } 1856 } 1857 else if (watched == mMainWnd) 1858 { 1859 switch (e->type()) 1860 { 1861 #if defined (Q_WS_WIN32) 1862 #if defined (VBOX_GUI_USE_DDRAW) 1863 case QEvent::Move: 1864 { 1865 /* 1866 * notification from our parent that it has moved. We need this 1867 * in order to possibly adjust the direct screen blitting. 1868 */ 1869 if (mFrameBuf) 1870 mFrameBuf->moveEvent ((QMoveEvent *) e); 1871 break; 1872 } 1873 #endif 1874 /* 1875 * install/uninstall low-level kbd hook on every 1876 * activation/deactivation to: 1877 * a) avoid excess hook calls when we're not active and 1878 * b) be always in front of any other possible hooks 1879 */ 1880 case QEvent::WindowActivate: 1881 { 1882 gKbdHook = SetWindowsHookEx (WH_KEYBOARD_LL, lowLevelKeyboardProc, 1883 GetModuleHandle (NULL), 0); 1884 AssertMsg (gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError())); 1885 break; 1886 } 1887 case QEvent::WindowDeactivate: 1888 { 1889 if (gKbdHook) 1890 { 1891 UnhookWindowsHookEx (gKbdHook); 1892 gKbdHook = NULL; 1893 } 1894 break; 1895 } 1896 #endif /* defined (Q_WS_WIN32) */ 1897 #if defined (Q_WS_MAC) 1898 /* 1899 * Install/remove the keyboard event handler. 1900 */ 1901 case QEvent::WindowActivate: 1902 darwinGrabKeyboardEvents (true); 1903 break; 1904 case QEvent::WindowDeactivate: 1905 darwinGrabKeyboardEvents (false); 1906 break; 1907 #endif /* defined (Q_WS_MAC) */ 1908 case QEvent::Resize: 1909 { 1910 /* Set the "guest needs to resize" hint. This hint is acted upon 1911 * when (and only when) the autoresize property is "true". */ 1912 mDoResize = mGuestSupportsGraphics || mMainWnd->isTrueFullscreen(); 1913 if (!mIgnoreMainwndResize && 1914 mGuestSupportsGraphics && mAutoresizeGuest) 1915 QTimer::singleShot (300, this, SLOT (doResizeHint())); 1916 break; 1917 } 1918 case QEvent::WindowStateChange: 1919 { 1920 /* During minimizing and state restoring mMainWnd gets the focus 1921 * which belongs to console view window, so returning it properly. */ 1922 QWindowStateChangeEvent *ev = static_cast <QWindowStateChangeEvent*> (e); 1923 if (ev->oldState() & Qt::WindowMinimized) 1924 { 1925 if (QApplication::focusWidget()) 1926 { 1927 QApplication::focusWidget()->clearFocus(); 1928 qApp->processEvents(); 1929 } 1930 QTimer::singleShot (0, this, SLOT (setFocus())); 1931 } 1932 break; 1933 } 1934 1935 default: 1936 break; 1937 } 1938 } 1939 else if (watched == mMainWnd->menuBar()) 1940 { 1941 /* 1942 * sometimes when we press ESC in the menu it brings the 1943 * focus away (Qt bug?) causing no widget to have a focus, 1944 * or holds the focus itself, instead of returning the focus 1945 * to the console window. here we fix this. 1946 */ 1947 switch (e->type()) 1948 { 1949 case QEvent::FocusOut: 1950 { 1951 if (qApp->focusWidget() == 0) 1952 setFocus(); 1953 break; 1954 } 1955 case QEvent::KeyPress: 1956 { 1957 QKeyEvent *ke = (QKeyEvent *) e; 1958 if (ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier)) 1959 if (mMainWnd->menuBar()->hasFocus()) 1960 setFocus(); 1961 break; 1962 } 1963 default: 1964 break; 1965 } 1966 } 1967 1968 return QAbstractScrollArea::eventFilter (watched, e); 1969 } 1970 1971 #if defined(Q_WS_WIN32) 1972 1973 /** 1974 * Low-level keyboard event handler, 1975 * @return 1976 * true to indicate that the message is processed and false otherwise 1977 */ 1978 bool VBoxConsoleView::winLowKeyboardEvent (UINT msg, const KBDLLHOOKSTRUCT &event) 1979 { 1980 #if 0 1981 LogFlow (("### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X (mKbdCaptured=%d)\n", 1982 event.vkCode, event.scanCode, event.flags, event.dwExtraInfo, mKbdCaptured)); 1983 char buf [256]; 1984 sprintf (buf, "### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X", 1985 event.vkCode, event.scanCode, event.flags, event.dwExtraInfo); 1986 mMainWnd->statusBar()->message (buf); 1987 #endif 1988 1989 /* Sometimes it happens that Win inserts additional events on some key 1990 * press/release. For example, it prepends ALT_GR in German layout with 1991 * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary 1992 * to specially treat ALT_GR to enter additional chars to regular apps). 1993 * These events are definitely unwanted in VM, so filter them out. */ 1994 /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan 1995 * code 0x23a. If this is not passed through then it is impossible to 1996 * cancel CapsLock on a French keyboard. I didn't find any other examples 1997 * of these strange events. Let's hope we are not missing anything else 1998 * of importance! */ 1999 if (hasFocus() && (event.scanCode & ~0xFF)) 2000 { 2001 if (event.vkCode == VK_CAPITAL) 2002 return false; 2003 else 2004 return true; 2005 } 2006 2007 if (!mKbdCaptured) 2008 return false; 2009 2010 /* it's possible that a key has been pressed while the keyboard was not 2011 * captured, but is being released under the capture. Detect this situation 2012 * and return false to let Windows process the message normally and update 2013 * its key state table (to avoid the stuck key effect). */ 2014 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) 2015 ? IsExtKeyPressed 2016 : IsKeyPressed; 2017 if ((event.flags & 0x80) /* released */ && 2018 ((event.vkCode == gs.hostKey() && !hostkey_in_capture) || 2019 (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed)) 2020 return false; 2021 2022 MSG message; 2023 message.hwnd = winId(); 2024 message.message = msg; 2025 message.wParam = event.vkCode; 2026 message.lParam = 2027 1 | 2028 (event.scanCode & 0xFF) << 16 | 2029 (event.flags & 0xFF) << 24; 2030 2031 /* Windows sets here the extended bit when the Right Shift key is pressed, 2032 * which is totally wrong. Undo it. */ 2033 if (event.vkCode == VK_RSHIFT) 2034 message.lParam &= ~0x1000000; 2035 2036 /* we suppose here that this hook is always called on the main GUI thread */ 2037 long dummyResult; 2038 return winEvent (&message, &dummyResult); 2039 } 2040 2041 /** 2042 * Get Win32 messages before they are passed to Qt. This allows us to get 2043 * the keyboard events directly and bypass the harmful Qt translation. A 2044 * return value of @c true indicates to Qt that the event has been handled. 2045 */ 2046 bool VBoxConsoleView::winEvent (MSG *aMsg, long* /* aResult */) 2047 { 2048 if (!mAttached || ! ( 2049 aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN || 2050 aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP 2051 )) 2052 return false; 2053 2054 /* check for the special flag possibly set at the end of this function */ 2055 if (aMsg->lParam & (0x1 << 25)) 2056 { 2057 aMsg->lParam &= ~(0x1 << 25); 2058 return false; 2059 } 2060 2061 #if 0 2062 char buf [256]; 2063 sprintf (buf, "WM_%04X: vk=%04X rep=%05d scan=%02X ext=%01d rzv=%01X ctx=%01d prev=%01d tran=%01d", 2064 aMsg->message, aMsg->wParam, 2065 (aMsg->lParam & 0xFFFF), 2066 ((aMsg->lParam >> 16) & 0xFF), 2067 ((aMsg->lParam >> 24) & 0x1), 2068 ((aMsg->lParam >> 25) & 0xF), 2069 ((aMsg->lParam >> 29) & 0x1), 2070 ((aMsg->lParam >> 30) & 0x1), 2071 ((aMsg->lParam >> 31) & 0x1)); 2072 mMainWnd->statusBar()->message (buf); 2073 LogFlow (("%s\n", buf)); 2074 #endif 2075 2076 int scan = (aMsg->lParam >> 16) & 0x7F; 2077 /* scancodes 0x80 and 0x00 are ignored */ 2078 if (!scan) 2079 return true; 2080 2081 int vkey = aMsg->wParam; 2082 2083 /* When one of the SHIFT keys is held and one of the cursor movement 2084 * keys is pressed, Windows duplicates SHIFT press/release messages, 2085 * but with the virtual key code set to 0xFF. These virtual keys are also 2086 * sent in some other situations (Pause, PrtScn, etc.). Ignore such 2087 * messages. */ 2088 if (vkey == 0xFF) 2089 return true; 2090 2091 int flags = 0; 2092 if (aMsg->lParam & 0x1000000) 2093 flags |= KeyExtended; 2094 if (!(aMsg->lParam & 0x80000000)) 2095 flags |= KeyPressed; 2096 2097 switch (vkey) 2098 { 2099 case VK_SHIFT: 2100 case VK_CONTROL: 2101 case VK_MENU: 2102 { 2103 /* overcome stupid Win32 modifier key generalization */ 2104 int keyscan = scan; 2105 if (flags & KeyExtended) 2106 keyscan |= 0xE000; 2107 switch (keyscan) 2108 { 2109 case 0x002A: vkey = VK_LSHIFT; break; 2110 case 0x0036: vkey = VK_RSHIFT; break; 2111 case 0x001D: vkey = VK_LCONTROL; break; 2112 case 0xE01D: vkey = VK_RCONTROL; break; 2113 case 0x0038: vkey = VK_LMENU; break; 2114 case 0xE038: vkey = VK_RMENU; break; 2115 } 2116 break; 2117 } 2118 case VK_NUMLOCK: 2119 /* Win32 sets the extended bit for the NumLock key. Reset it. */ 2120 flags &= ~KeyExtended; 2121 break; 2122 case VK_SNAPSHOT: 2123 flags |= KeyPrint; 2124 break; 2125 case VK_PAUSE: 2126 flags |= KeyPause; 2127 break; 2128 } 2129 2130 bool result = keyEvent (vkey, scan, flags); 2131 if (!result && mKbdCaptured) 2132 { 2133 /* keyEvent() returned that it didn't process the message, but since the 2134 * keyboard is captured, we don't want to pass it to Windows. We just want 2135 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 2136 * shortcuts for example). So send it direcltly to the window with the 2137 * special flag in the reserved area of lParam (to avoid recursion). */ 2138 ::SendMessage (aMsg->hwnd, aMsg->message, 2139 aMsg->wParam, aMsg->lParam | (0x1 << 25)); 2140 return true; 2141 } 2142 2143 /* These special keys have to be handled by Windows as well to update the 2144 * internal modifier state and to enable/disable the keyboard LED */ 2145 if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT) 2146 return false; 2147 2148 return result; 2149 } 2150 2151 #elif defined (Q_WS_PM) 2152 2153 /** 2154 * Get PM messages before they are passed to Qt. This allows us to get 2155 * the keyboard events directly and bypass the harmful Qt translation. A 2156 * return value of @c true indicates to Qt that the event has been handled. 2157 */ 2158 bool VBoxConsoleView::pmEvent (QMSG *aMsg) 2159 { 2160 if (!mAttached) 2161 return false; 2162 2163 if (aMsg->msg == UM_PREACCEL_CHAR) 2164 { 2165 /* we are inside the input hook */ 2166 2167 /* let the message go through the normal system pipeline */ 2168 if (!mKbdCaptured) 2169 return false; 2170 } 2171 2172 if (aMsg->msg != WM_CHAR && 2173 aMsg->msg != UM_PREACCEL_CHAR) 2174 return false; 2175 2176 /* check for the special flag possibly set at the end of this function */ 2177 if (SHORT2FROMMP (aMsg->mp2) & 0x8000) 2178 { 2179 aMsg->mp2 = MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), 2180 SHORT2FROMMP (aMsg->mp2) & ~0x8000); 2181 return false; 2182 } 2183 2184 #if 0 2185 { 2186 char buf [256]; 2187 sprintf (buf, "*** %s: f=%04X rep=%03d scan=%02X ch=%04X vk=%04X", 2188 (aMsg->msg == WM_CHAR ? "WM_CHAR" : "UM_PREACCEL_CHAR"), 2189 SHORT1FROMMP (aMsg->mp1), CHAR3FROMMP (aMsg->mp1), 2190 CHAR4FROMMP (aMsg->mp1), SHORT1FROMMP (aMsg->mp2), 2191 SHORT2FROMMP (aMsg->mp2)); 2192 mMainWnd->statusBar()->message (buf); 2193 LogFlow (("%s\n", buf)); 2194 } 2195 #endif 2196 2197 USHORT ch = SHORT1FROMMP (aMsg->mp2); 2198 USHORT f = SHORT1FROMMP (aMsg->mp1); 2199 2200 int scan = (unsigned int) CHAR4FROMMP (aMsg->mp1); 2201 if (!scan || scan > 0x7F) 2202 return true; 2203 2204 int vkey = QIHotKeyEdit::virtualKey (aMsg); 2205 2206 int flags = 0; 2207 2208 if ((ch & 0xFF) == 0xE0) 2209 { 2210 flags |= KeyExtended; 2211 scan = ch >> 8; 2212 } 2213 else if (scan == 0x5C && (ch & 0xFF) == '/') 2214 { 2215 /* this is the '/' key on the keypad */ 2216 scan = 0x35; 2217 flags |= KeyExtended; 2218 } 2219 else 2220 { 2221 /* For some keys, the scan code passed in QMSG is a pseudo scan 2222 * code. We replace it with a real hardware scan code, according to 2223 * http://www.computer-engineering.org/ps2keyboard/scancodes1.html. 2224 * Also detect Pause and PrtScn and set flags. */ 2225 switch (vkey) 2226 { 2227 case VK_ENTER: scan = 0x1C; flags |= KeyExtended; break; 2228 case VK_CTRL: scan = 0x1D; flags |= KeyExtended; break; 2229 case VK_ALTGRAF: scan = 0x38; flags |= KeyExtended; break; 2230 case VK_LWIN: scan = 0x5B; flags |= KeyExtended; break; 2231 case VK_RWIN: scan = 0x5C; flags |= KeyExtended; break; 2232 case VK_WINMENU: scan = 0x5D; flags |= KeyExtended; break; 2233 case VK_FORWARD: scan = 0x69; flags |= KeyExtended; break; 2234 case VK_BACKWARD: scan = 0x6A; flags |= KeyExtended; break; 2235 #if 0 2236 /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully 2237 // clear what is more correct 2238 case VK_BREAK: scan = 0x46; flags |= KeyExtended; break; 2239 #else 2240 case VK_BREAK: scan = 0; flags |= KeyPause; break; 2241 #endif 2242 case VK_PAUSE: scan = 0; flags |= KeyPause; break; 2243 case VK_PRINTSCRN: scan = 0; flags |= KeyPrint; break; 2244 default:; 2245 } 2246 } 2247 2248 if (!(f & KC_KEYUP)) 2249 flags |= KeyPressed; 2250 2251 bool result = keyEvent (vkey, scan, flags); 2252 if (!result && mKbdCaptured) 2253 { 2254 /* keyEvent() returned that it didn't process the message, but since the 2255 * keyboard is captured, we don't want to pass it to PM. We just want 2256 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 2257 * shortcuts for example). So send it direcltly to the window with the 2258 * special flag in the reserved area of lParam (to avoid recursion). */ 2259 ::WinSendMsg (aMsg->hwnd, WM_CHAR, 2260 aMsg->mp1, 2261 MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), 2262 SHORT2FROMMP (aMsg->mp2) | 0x8000)); 2263 return true; 2264 } 2265 return result; 2266 } 2267 2268 #elif defined(Q_WS_X11) 2269 2270 /** 2271 * This function is a "predicate" for XCheckIfEvent(). It will check 2272 * the XEvent passed to it to see if it is a keypress event matching 2273 * the keyrelease event in @a pvArg. 2274 * @returns True if the event matches, False otherwise 2275 * @param pEvent the event to compare, taken from the event queue 2276 * @param pvArg the keyrelease event we would like to compare against 2277 */ 2278 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, 2279 XPointer pvArg) 2280 { 2281 XEvent *pKeyEvent = (XEvent *) pvArg; 2282 if ((pEvent->type == XKeyPress) && 2283 (pEvent->xkey.keycode == pKeyEvent->xkey.keycode)) 2284 return True; 2285 else 2286 return False; 2287 } 2288 2289 /** 2290 * This routine gets X11 events before they are processed by Qt. This is 2291 * used for our platform specific keyboard implementation. A return value 2292 * of TRUE indicates that the event has been processed by us. 2293 */ 2294 bool VBoxConsoleView::x11Event (XEvent *event) 2295 { 2296 switch (event->type) 2297 { 2298 /* We have to handle XFocusOut right here as this event is not passed 2299 * to VBoxConsoleView::event(). Handling this event is important for 2300 * releasing the keyboard before the screen saver gets active. */ 2301 case XFocusOut: 2302 case XFocusIn: 2303 if (isRunning()) 2304 focusEvent (event->type == XFocusIn); 2305 return false; 2306 case XKeyPress: 2307 case XKeyRelease: 2308 if (mAttached) 2309 break; 2310 /* else fall through */ 2311 default: 2312 return false; /* pass the event to Qt */ 2313 } 2314 2315 /* Translate the keycode to a PC scan code. */ 2316 unsigned scan = handleXKeyEvent (event); 2317 2318 #if 0 2319 char buf [256]; 2320 sprintf (buf, "pr=%d kc=%08X st=%08X extended=%s scan=%04X", 2321 event->type == XKeyPress ? 1 : 0, event->xkey.keycode, 2322 event->xkey.state, scan >> 8 ? "true" : "false", scan & 0x7F); 2323 mMainWnd->statusBar()->message (buf); 2324 LogFlow (("### %s\n", buf)); 2325 #endif 2326 2327 // scancodes 0x00 (no valid translation) and 0x80 are ignored 2328 if (!scan & 0x7F) 2329 return true; 2330 2331 /* Fix for http://www.virtualbox.org/ticket/1296: 2332 * when X11 sends events for repeated keys, it always inserts an 2333 * XKeyRelease before the XKeyPress. */ 2334 XEvent returnEvent; 2335 if ((event->type == XKeyRelease) && 2336 (XCheckIfEvent(event->xkey.display, &returnEvent, 2337 VBoxConsoleViewCompEvent, (XPointer) event) == True)) { 2338 XPutBackEvent(event->xkey.display, &returnEvent); 2339 /* Discard it, don't pass it to Qt. */ 2340 return true; 2341 } 2342 2343 KeySym ks = ::XKeycodeToKeysym (event->xkey.display, event->xkey.keycode, 0); 2344 2345 int flags = 0; 2346 if (scan >> 8) 2347 flags |= KeyExtended; 2348 if (event->type == XKeyPress) 2349 flags |= KeyPressed; 2350 2351 /* Remove the extended flag */ 2352 scan &= 0x7F; 2353 2354 switch (ks) 2355 { 2356 case XK_Print: 2357 flags |= KeyPrint; 2358 break; 2359 case XK_Pause: 2360 if (event->xkey.state & ControlMask) /* Break */ 2361 { 2362 ks = XK_Break; 2363 flags |= KeyExtended; 2364 scan = 0x46; 2365 } 2366 else 2367 flags |= KeyPause; 2368 break; 2369 } 2370 2371 return keyEvent (ks, scan, flags); 2372 } 2373 2374 #elif defined (Q_WS_MAC) 2375 2376 /** 2377 * Invoked by VBoxConsoleView::darwinEventHandlerProc / VBoxConsoleView::macEventFilter when 2378 * it receives a raw keyboard event. 2379 * 2380 * @param pvCocoaEvent The Cocoa keyboard event. Can be NULL in some configs. 2381 * @param inEvent The keyboard event. 2382 * 2383 * @return true if the key was processed, false if it wasn't processed and should be passed on. 2384 */ 2385 bool VBoxConsoleView::darwinKeyboardEvent (const void *pvCocoaEvent, EventRef inEvent) 2386 { 2387 bool ret = false; 2388 UInt32 EventKind = ::GetEventKind (inEvent); 2389 if (EventKind != kEventRawKeyModifiersChanged) 2390 { 2391 /* convert keycode to set 1 scan code. */ 2392 UInt32 keyCode = ~0U; 2393 ::GetEventParameter (inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode); 2394 unsigned scanCode = ::DarwinKeycodeToSet1Scancode (keyCode); 2395 if (scanCode) 2396 { 2397 /* calc flags. */ 2398 int flags = 0; 2399 if (EventKind != kEventRawKeyUp) 2400 flags |= KeyPressed; 2401 if (scanCode & VBOXKEY_EXTENDED) 2402 flags |= KeyExtended; 2403 /** @todo KeyPause, KeyPrint. */ 2404 scanCode &= VBOXKEY_SCANCODE_MASK; 2405 2406 /* get the unicode string (if present). */ 2407 AssertCompileSize (wchar_t, 2); 2408 AssertCompileSize (UniChar, 2); 2409 ByteCount cbWritten = 0; 2410 wchar_t ucs[8]; 2411 if (::GetEventParameter (inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 2412 sizeof (ucs), &cbWritten, &ucs[0]) != 0) 2413 cbWritten = 0; 2414 ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */ 2415 2416 ret = keyEvent (keyCode, scanCode, flags, ucs[0] ? ucs : NULL); 2417 } 2418 } 2419 else 2420 { 2421 /* May contain multiple modifier changes, kind of annoying. */ 2422 UInt32 newMask = 0; 2423 ::GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, 2424 sizeof (newMask), NULL, &newMask); 2425 newMask = ::DarwinAdjustModifierMask (newMask, pvCocoaEvent); 2426 UInt32 changed = newMask ^ mDarwinKeyModifiers; 2427 if (changed) 2428 { 2429 for (UInt32 bit = 0; bit < 32; bit++) 2430 { 2431 if (!(changed & (1 << bit))) 2432 continue; 2433 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode (1 << bit); 2434 if (!scanCode) 2435 continue; 2436 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode (1 << bit); 2437 Assert (keyCode); 2438 2439 if (!(scanCode & VBOXKEY_LOCK)) 2440 { 2441 unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0; 2442 if (scanCode & VBOXKEY_EXTENDED) 2443 flags |= KeyExtended; 2444 scanCode &= VBOXKEY_SCANCODE_MASK; 2445 ret |= keyEvent (keyCode, scanCode & 0xff, flags); 2446 } 2447 else 2448 { 2449 unsigned flags = 0; 2450 if (scanCode & VBOXKEY_EXTENDED) 2451 flags |= KeyExtended; 2452 scanCode &= VBOXKEY_SCANCODE_MASK; 2453 keyEvent (keyCode, scanCode, flags | KeyPressed); 2454 keyEvent (keyCode, scanCode, flags); 2455 } 2456 } 2457 } 2458 2459 mDarwinKeyModifiers = newMask; 2460 2461 /* Always return true here because we'll otherwise getting a Qt event 2462 we don't want and that will only cause the Pause warning to pop up. */ 2463 ret = true; 2464 } 2465 2466 return ret; 2467 } 2468 2469 2470 /** 2471 * Installs or removes the keyboard event handler. 2472 * 2473 * @param fGrab True if we're to grab the events, false if we're not to. 2474 */ 2475 void VBoxConsoleView::darwinGrabKeyboardEvents (bool fGrab) 2476 { 2477 mKeyboardGrabbed = fGrab; 2478 if (fGrab) 2479 { 2480 /* Disable mouse and keyboard event compression/delaying to make sure 2481 we *really* get all of the events. */ 2482 ::CGSetLocalEventsSuppressionInterval (0.0); 2483 setMouseCoalescingEnabled (false); 2484 2485 /* Register the event callback/hook and grab the keyboard. */ 2486 # ifdef QT_MAC_USE_COCOA 2487 ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */ 2488 VBoxConsoleView::darwinEventHandlerProc, this); 2489 2490 # elif !defined (VBOX_WITH_HACKED_QT) 2491 EventTypeSpec eventTypes[6]; 2492 eventTypes[0].eventClass = kEventClassKeyboard; 2493 eventTypes[0].eventKind = kEventRawKeyDown; 2494 eventTypes[1].eventClass = kEventClassKeyboard; 2495 eventTypes[1].eventKind = kEventRawKeyUp; 2496 eventTypes[2].eventClass = kEventClassKeyboard; 2497 eventTypes[2].eventKind = kEventRawKeyRepeat; 2498 eventTypes[3].eventClass = kEventClassKeyboard; 2499 eventTypes[3].eventKind = kEventRawKeyModifiersChanged; 2500 /* For ignorning Command-H and Command-Q which aren't affected by the 2501 * global hotkey stuff (doesn't work well): */ 2502 eventTypes[4].eventClass = kEventClassCommand; 2503 eventTypes[4].eventKind = kEventCommandProcess; 2504 eventTypes[5].eventClass = kEventClassCommand; 2505 eventTypes[5].eventKind = kEventCommandUpdateStatus; 2506 2507 EventHandlerUPP eventHandler = ::NewEventHandlerUPP (VBoxConsoleView::darwinEventHandlerProc); 2508 2509 mDarwinEventHandlerRef = NULL; 2510 ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 2511 this, &mDarwinEventHandlerRef); 2512 ::DisposeEventHandlerUPP (eventHandler); 2513 2514 # else /* VBOX_WITH_HACKED_QT */ 2515 ((QIApplication *)qApp)->setEventFilter (VBoxConsoleView::macEventFilter, this); 2516 # endif /* VBOX_WITH_HACKED_QT */ 2517 2518 ::DarwinGrabKeyboard (false); 2519 } 2520 else 2521 { 2522 ::DarwinReleaseKeyboard(); 2523 # ifdef QT_MAC_USE_COCOA 2524 ::VBoxCocoaApplication_unsetCallback (UINT32_MAX, /** @todo fix mask */ 2525 VBoxConsoleView::darwinEventHandlerProc, this); 2526 # elif !defined(VBOX_WITH_HACKED_QT) 2527 if (mDarwinEventHandlerRef) 2528 { 2529 ::RemoveEventHandler (mDarwinEventHandlerRef); 2530 mDarwinEventHandlerRef = NULL; 2531 } 2532 # else /* VBOX_WITH_HACKED_QT */ 2533 ((QIApplication *)qApp)->setEventFilter (NULL, NULL); 2534 # endif /* VBOX_WITH_HACKED_QT */ 2535 } 2536 } 2537 2538 #endif // defined (Q_WS_MAC) 2539 2540 // 2541 // Private members 2542 ///////////////////////////////////////////////////////////////////////////// 2543 2544 /** 2545 * Called on every focus change and also to forcibly capture/uncapture the 2546 * input in situations similar to gaining or losing focus. 2547 * 2548 * @param aHasFocus true if the window got focus and false otherwise. 2549 * @param aReleaseHostKey true to release the host key (used only when 2550 * @a aHasFocus is false. 2551 */ 2552 void VBoxConsoleView::focusEvent (bool aHasFocus, 2553 bool aReleaseHostKey /* = true */) 2554 { 2555 if (aHasFocus) 2556 { 2557 #ifdef RT_OS_WINDOWS 2558 if ( !mDisableAutoCapture && gs.autoCapture() 2559 && GetAncestor (winId(), GA_ROOT) == GetForegroundWindow()) 2560 #else 2561 if (!mDisableAutoCapture && gs.autoCapture()) 2562 #endif /* RT_OS_WINDOWS */ 2563 { 2564 captureKbd (true); 2565 /// @todo (dmik) 2566 // the below is for the mouse auto-capture. disabled for now. in order to 2567 // properly support it, we need to know when *all* mouse buttons are 2568 // released after we got focus, and grab the mouse only after then. 2569 // btw, the similar would be good the for keyboard auto-capture, too. 2570 // if (!(mMouseAbsolute && mMouseIntegration)) 2571 // captureMouse (true); 2572 } 2573 2574 /* reset the single-time disable capture flag */ 2575 if (mDisableAutoCapture) 2576 mDisableAutoCapture = false; 2577 } 2578 else 2579 { 2580 captureMouse (false); 2581 captureKbd (false, false); 2582 releaseAllPressedKeys (aReleaseHostKey); 2583 } 2584 } 2585 2586 /** 2587 * Synchronize the views of the host and the guest to the modifier keys. 2588 * This function will add up to 6 additional keycodes to codes. 2589 * 2590 * @param codes pointer to keycodes which are sent to the keyboard 2591 * @param count pointer to the keycodes counter 2592 */ 2593 void VBoxConsoleView::fixModifierState (LONG *codes, uint *count) 2594 { 2595 #if defined(Q_WS_X11) 2596 2597 Window wDummy1, wDummy2; 2598 int iDummy3, iDummy4, iDummy5, iDummy6; 2599 unsigned uMask; 2600 unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0; 2601 2602 uKeyMaskCaps = LockMask; 2603 XModifierKeymap* map = XGetModifierMapping(QX11Info::display()); 2604 KeyCode keyCodeNum = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock); 2605 KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock); 2606 2607 for (int i = 0; i < 8; i++) 2608 { 2609 if ( keyCodeNum != NoSymbol 2610 && map->modifiermap[map->max_keypermod * i] == keyCodeNum) 2611 uKeyMaskNum = 1 << i; 2612 else if ( keyCodeScroll != NoSymbol 2613 && map->modifiermap[map->max_keypermod * i] == keyCodeScroll) 2614 uKeyMaskScroll = 1 << i; 2615 } 2616 XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2, 2617 &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask); 2618 XFreeModifiermap(map); 2619 2620 if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum))) 2621 { 2622 muNumLockAdaptionCnt--; 2623 codes[(*count)++] = 0x45; 2624 codes[(*count)++] = 0x45 | 0x80; 2625 } 2626 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps))) 2627 { 2628 muCapsLockAdaptionCnt--; 2629 codes[(*count)++] = 0x3a; 2630 codes[(*count)++] = 0x3a | 0x80; 2631 /* Some keyboard layouts require shift to be pressed to break 2632 * capslock. For simplicity, only do this if shift is not 2633 * already held down. */ 2634 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2635 { 2636 codes[(*count)++] = 0x2a; 2637 codes[(*count)++] = 0x2a | 0x80; 2638 } 2639 } 2640 2641 #elif defined(Q_WS_WIN32) 2642 2643 if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK)))) 2644 { 2645 muNumLockAdaptionCnt--; 2646 codes[(*count)++] = 0x45; 2647 codes[(*count)++] = 0x45 | 0x80; 2648 } 2649 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL)))) 2650 { 2651 muCapsLockAdaptionCnt--; 2652 codes[(*count)++] = 0x3a; 2653 codes[(*count)++] = 0x3a | 0x80; 2654 /* Some keyboard layouts require shift to be pressed to break 2655 * capslock. For simplicity, only do this if shift is not 2656 * already held down. */ 2657 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2658 { 2659 codes[(*count)++] = 0x2a; 2660 codes[(*count)++] = 0x2a | 0x80; 2661 } 2662 } 2663 2664 #elif defined (Q_WS_MAC) 2665 2666 /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */ 2667 if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock))) 2668 { 2669 muCapsLockAdaptionCnt--; 2670 codes[(*count)++] = 0x3a; 2671 codes[(*count)++] = 0x3a | 0x80; 2672 /* Some keyboard layouts require shift to be pressed to break 2673 * capslock. For simplicity, only do this if shift is not 2674 * already held down. */ 2675 if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed)) 2676 { 2677 codes[(*count)++] = 0x2a; 2678 codes[(*count)++] = 0x2a | 0x80; 2679 } 2680 } 2681 2682 #else 2683 2684 //#warning Adapt VBoxConsoleView::fixModifierState 2685 2686 #endif 2687 2688 2689 } 2690 2691 /** 2692 * Called on enter/exit seamless/fullscreen mode. 2693 */ 2694 void VBoxConsoleView::toggleFSMode (const QSize &aSize) 2695 { 2696 if ((mGuestSupportsGraphics && mAutoresizeGuest) || 2697 mMainWnd->isTrueSeamless() || 2698 mMainWnd->isTrueFullscreen()) 2699 { 2700 QSize newSize; 2701 if (aSize.isValid()) 2702 { 2703 mNormalSize = aSize; 2704 newSize = maximumSize(); 2705 } 2706 else 2707 newSize = mNormalSize; 2708 doResizeHint (newSize); 2709 } 2710 2711 /* Reactivate the console window to preserve the focus position. 2712 * Else focus will move to the mini-tool-bar. */ 2713 activateWindow(); 2714 } 2715 2716 /** 2717 * Get the current available desktop geometry for the console/framebuffer 2718 * 2719 * @returns the geometry. An empty rectangle means unrestricted. 2720 */ 2721 QRect VBoxConsoleView::desktopGeometry() 2722 { 2723 QRect rc; 2724 switch (mDesktopGeo) 2725 { 2726 case DesktopGeo_Fixed: 2727 case DesktopGeo_Automatic: 2728 rc = QRect (0, 0, 2729 RT_MAX (mDesktopGeometry.width(), mStoredConsoleSize.width()), 2730 RT_MAX (mDesktopGeometry.height(), mStoredConsoleSize.height())); 2731 break; 2732 case DesktopGeo_Any: 2733 rc = QRect (0, 0, 0, 0); 2734 break; 2735 default: 2736 AssertMsgFailed (("Bad geometry type %d\n", mDesktopGeo)); 2737 } 2738 return rc; 2739 } 2740 2741 QRegion VBoxConsoleView::lastVisibleRegion() const 2742 { 2743 return mLastVisibleRegion; 2744 } 2745 2746 bool VBoxConsoleView::isAutoresizeGuestActive() 2747 { 2748 return mGuestSupportsGraphics && mAutoresizeGuest; 2749 } 2750 2751 /** 2752 * Called on every key press and release (while in focus). 2753 * 2754 * @param aKey virtual scan code (virtual key on Win32 and KeySym on X11) 2755 * @param aScan hardware scan code 2756 * @param aFlags flags, a combination of Key* constants 2757 * @param aUniKey Unicode translation of the key. Optional. 2758 * 2759 * @return true to consume the event and false to pass it to Qt 2760 */ 2761 bool VBoxConsoleView::keyEvent (int aKey, uint8_t aScan, int aFlags, 2762 wchar_t *aUniKey/* = NULL*/) 2763 { 2764 #if 0 2765 { 2766 char buf [256]; 2767 sprintf (buf, "aKey=%08X aScan=%02X aFlags=%08X", 2768 aKey, aScan, aFlags); 2769 mMainWnd->statusBar()->message (buf); 2770 } 2771 #endif 2772 2773 const bool isHostKey = aKey == gs.hostKey(); 2774 2775 LONG buf [16]; 2776 LONG *codes = buf; 2777 uint count = 0; 2778 uint8_t whatPressed = 0; 2779 2780 if (!isHostKey && !mIsHostkeyPressed) 2781 { 2782 if (aFlags & KeyPrint) 2783 { 2784 static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 }; 2785 static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA }; 2786 if (aFlags & KeyPressed) 2787 { 2788 codes = PrintMake; 2789 count = SIZEOF_ARRAY (PrintMake); 2790 } 2791 else 2792 { 2793 codes = PrintBreak; 2794 count = SIZEOF_ARRAY (PrintBreak); 2795 } 2796 } 2797 else if (aFlags & KeyPause) 2798 { 2799 if (aFlags & KeyPressed) 2800 { 2801 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 }; 2802 codes = Pause; 2803 count = SIZEOF_ARRAY (Pause); 2804 } 2805 else 2806 { 2807 /* Pause shall not produce a break code */ 2808 return true; 2809 } 2810 } 2811 else 2812 { 2813 if (aFlags & KeyPressed) 2814 { 2815 /* Check if the guest has the same view on the modifier keys (NumLock, 2816 * CapsLock, ScrollLock) as the X server. If not, send KeyPress events 2817 * to synchronize the state. */ 2818 fixModifierState (codes, &count); 2819 } 2820 2821 /* Check if it's C-A-D and GUI/PassCAD is not true */ 2822 if (!mPassCAD && 2823 aScan == 0x53 /* Del */ && 2824 ((mPressedKeys [0x38] & IsKeyPressed) /* Alt */ || 2825 (mPressedKeys [0x38] & IsExtKeyPressed)) && 2826 ((mPressedKeys [0x1d] & IsKeyPressed) /* Ctrl */ || 2827 (mPressedKeys [0x1d] & IsExtKeyPressed))) 2828 { 2829 /* Use the C-A-D combination as a last resort to get the 2830 * keyboard and mouse back to the host when the user forgets 2831 * the Host Key. Note that it's always possible to send C-A-D 2832 * to the guest using the Host+Del combination. BTW, it would 2833 * be preferrable to completely ignore C-A-D in guests, but 2834 * that's not possible because we cannot predict what other 2835 * keys will be pressed next when one of C, A, D is held. */ 2836 2837 if (isRunning() && mKbdCaptured) 2838 { 2839 captureKbd (false); 2840 if (!(mMouseAbsolute && mMouseIntegration)) 2841 captureMouse (false); 2842 } 2843 2844 return true; 2845 } 2846 2847 /* process the scancode and update the table of pressed keys */ 2848 whatPressed = IsKeyPressed; 2849 2850 if (aFlags & KeyExtended) 2851 { 2852 codes [count++] = 0xE0; 2853 whatPressed = IsExtKeyPressed; 2854 } 2855 2856 if (aFlags & KeyPressed) 2857 { 2858 codes [count++] = aScan; 2859 mPressedKeys [aScan] |= whatPressed; 2860 } 2861 else 2862 { 2863 /* if we haven't got this key's press message, we ignore its 2864 * release */ 2865 if (!(mPressedKeys [aScan] & whatPressed)) 2866 return true; 2867 codes [count++] = aScan | 0x80; 2868 mPressedKeys [aScan] &= ~whatPressed; 2869 } 2870 2871 if (mKbdCaptured) 2872 mPressedKeys [aScan] |= IsKbdCaptured; 2873 else 2874 mPressedKeys [aScan] &= ~IsKbdCaptured; 2875 } 2876 } 2877 else 2878 { 2879 /* currently this is used in winLowKeyboardEvent() only */ 2880 hostkey_in_capture = mKbdCaptured; 2881 } 2882 2883 bool emitSignal = false; 2884 int hotkey = 0; 2885 2886 /* process the host key */ 2887 if (aFlags & KeyPressed) 2888 { 2889 if (isHostKey) 2890 { 2891 if (!mIsHostkeyPressed) 2892 { 2893 mIsHostkeyPressed = mIsHostkeyAlone = true; 2894 if (isRunning()) 2895 saveKeyStates(); 2896 emitSignal = true; 2897 } 2898 } 2899 else 2900 { 2901 if (mIsHostkeyPressed) 2902 { 2903 if (mIsHostkeyAlone) 2904 { 2905 hotkey = aKey; 2906 mIsHostkeyAlone = false; 2907 } 2908 } 2909 } 2910 } 2911 else 2912 { 2913 if (isHostKey) 2914 { 2915 if (mIsHostkeyPressed) 2916 { 2917 mIsHostkeyPressed = false; 2918 2919 if (mIsHostkeyAlone) 2920 { 2921 if (isPaused()) 2922 { 2923 vboxProblem().remindAboutPausedVMInput(); 2924 } 2925 else 2926 if (isRunning()) 2927 { 2928 bool captured = mKbdCaptured; 2929 bool ok = true; 2930 if (!captured) 2931 { 2932 /* temporarily disable auto capture that will take 2933 * place after this dialog is dismissed because 2934 * the capture state is to be defined by the 2935 * dialog result itself */ 2936 mDisableAutoCapture = true; 2937 bool autoConfirmed = false; 2938 ok = vboxProblem().confirmInputCapture (&autoConfirmed); 2939 if (autoConfirmed) 2940 mDisableAutoCapture = false; 2941 /* otherwise, the disable flag will be reset in 2942 * the next console view's foucs in event (since 2943 * may happen asynchronously on some platforms, 2944 * after we return from this code) */ 2945 } 2946 2947 if (ok) 2948 { 2949 captureKbd (!captured, false); 2950 if (!(mMouseAbsolute && mMouseIntegration)) 2951 { 2952 #ifdef Q_WS_X11 2953 /* make sure that pending FocusOut events from the 2954 * previous message box are handled, otherwise the 2955 * mouse is immediately ungrabbed. */ 2956 qApp->processEvents(); 2957 #endif 2958 captureMouse (mKbdCaptured); 2959 } 2960 } 2961 } 2962 } 2963 2964 if (isRunning()) 2965 sendChangedKeyStates(); 2966 2967 emitSignal = true; 2968 } 2969 } 2970 else 2971 { 2972 if (mIsHostkeyPressed) 2973 mIsHostkeyAlone = false; 2974 } 2975 } 2976 2977 /* emit the keyboard state change signal */ 2978 if (emitSignal) 2979 emitKeyboardStateChanged(); 2980 2981 /* Process Host+<key> shortcuts. currently, <key> is limited to 2982 * alphanumeric chars. Other Host+<key> combinations are handled in 2983 * event(). */ 2984 if (hotkey) 2985 { 2986 bool processed = false; 2987 #if defined (Q_WS_WIN32) 2988 NOREF(aUniKey); 2989 int n = GetKeyboardLayoutList (0, NULL); 2990 Assert (n); 2991 HKL *list = new HKL [n]; 2992 GetKeyboardLayoutList (n, list); 2993 for (int i = 0; i < n && !processed; i++) 2994 { 2995 wchar_t ch; 2996 static BYTE keys [256] = {0}; 2997 if (!ToUnicodeEx (hotkey, 0, keys, &ch, 1, 0, list [i]) == 1) 2998 ch = 0; 2999 if (ch) 3000 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 3001 QChar (ch).toUpper().unicode()), 3002 mMainWnd->menuBar()->actions()); 3003 } 3004 delete[] list; 3005 #elif defined (Q_WS_X11) 3006 NOREF(aUniKey); 3007 Display *display = QX11Info::display(); 3008 int keysyms_per_keycode = getKeysymsPerKeycode(); 3009 KeyCode kc = XKeysymToKeycode (display, aKey); 3010 // iterate over the first level (not shifted) keysyms in every group 3011 for (int i = 0; i < keysyms_per_keycode && !processed; i += 2) 3012 { 3013 KeySym ks = XKeycodeToKeysym (display, kc, i); 3014 char ch = 0; 3015 if (!XkbTranslateKeySym (display, &ks, 0, &ch, 1, NULL) == 1) 3016 ch = 0; 3017 if (ch) 3018 { 3019 QChar c = QString::fromLocal8Bit (&ch, 1) [0]; 3020 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 3021 c.toUpper().unicode()), 3022 mMainWnd->menuBar()->actions()); 3023 } 3024 } 3025 #elif defined (Q_WS_MAC) 3026 if (aUniKey && aUniKey [0] && !aUniKey [1]) 3027 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 3028 QChar (aUniKey [0]).toUpper().unicode()), 3029 mMainWnd->menuBar()->actions()); 3030 3031 /* Don't consider the hot key as pressed since the guest never saw 3032 * it. (probably a generic thing) */ 3033 mPressedKeys [aScan] &= ~whatPressed; 3034 #endif 3035 3036 /* grab the key from Qt if processed, or pass it to Qt otherwise 3037 * in order to process non-alphanumeric keys in event(), after they are 3038 * converted to Qt virtual keys. */ 3039 return processed; 3040 } 3041 3042 /* no more to do, if the host key is in action or the VM is paused */ 3043 if (mIsHostkeyPressed || isHostKey || isPaused()) 3044 { 3045 /* grab the key from Qt and from VM if it's a host key, 3046 * otherwise just pass it to Qt */ 3047 return isHostKey; 3048 } 3049 3050 CKeyboard keyboard = mConsole.GetKeyboard(); 3051 Assert (!keyboard.isNull()); 3052 3053 #if defined (Q_WS_WIN32) 3054 /* send pending WM_PAINT events */ 3055 ::UpdateWindow (viewport()->winId()); 3056 #endif 3057 3058 #if 0 3059 { 3060 char buf [256]; 3061 sprintf (buf, "*** SCANS: "); 3062 for (uint i = 0; i < count; ++ i) 3063 sprintf (buf + strlen (buf), "%02X ", codes [i]); 3064 mMainWnd->statusBar()->message (buf); 3065 LogFlow (("%s\n", buf)); 3066 } 3067 #endif 3068 3069 std::vector <LONG> scancodes(codes, &codes[count]); 3070 keyboard.PutScancodes (QVector<LONG>::fromStdVector(scancodes)); 3071 3072 /* grab the key from Qt */ 3073 return true; 3074 } 3075 3076 /** 3077 * Called on every mouse/wheel move and button press/release. 3078 * 3079 * @return true to consume the event and false to pass it to Qt 3080 */ 3081 bool VBoxConsoleView::mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos, 3082 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 3083 int aWheelDelta, Qt::Orientation aWheelDir) 3084 { 3085 #if 1 3086 3087 LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n", 3088 __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(), 3089 (aButtons & Qt::LeftButton ? 1 : 0) 3090 | (aButtons & Qt::RightButton ? 2 : 0) 3091 | (aButtons & Qt::MidButton ? 4 : 0) 3092 | (aButtons & Qt::XButton1 ? 8 : 0) 3093 | (aButtons & Qt::XButton2 ? 16 : 0), 3094 aWheelDelta, 3095 aWheelDir == Qt::Horizontal ? "Horizontal" 3096 : aWheelDir == Qt::Vertical ? "Vertical" : "Unknown")); 3097 Q_UNUSED (aModifiers); 3098 #else 3099 Q_UNUSED (aModifiers); 3100 #endif 3101 3102 int state = 0; 3103 if (aButtons & Qt::LeftButton) 3104 state |= KMouseButtonState_LeftButton; 3105 if (aButtons & Qt::RightButton) 3106 state |= KMouseButtonState_RightButton; 3107 if (aButtons & Qt::MidButton) 3108 state |= KMouseButtonState_MiddleButton; 3109 if (aButtons & Qt::XButton1) 3110 state |= KMouseButtonState_XButton1; 3111 if (aButtons & Qt::XButton2) 3112 state |= KMouseButtonState_XButton2; 3113 3114 #ifdef Q_WS_MAC 3115 /* Simulate the right click on 3116 * Host+Left Mouse */ 3117 if (mIsHostkeyPressed && 3118 mIsHostkeyAlone && 3119 state == KMouseButtonState_LeftButton) 3120 state = KMouseButtonState_RightButton; 3121 #endif /* Q_WS_MAC */ 3122 3123 int wheelVertical = 0; 3124 int wheelHorizontal = 0; 3125 if (aWheelDir == Qt::Vertical) 3126 { 3127 /* the absolute value of wheel delta is 120 units per every wheel 3128 * move; positive deltas correspond to counterclockwize rotations 3129 * (usually up), negative -- to clockwize (usually down). */ 3130 wheelVertical = - (aWheelDelta / 120); 3131 } 3132 else if (aWheelDir == Qt::Horizontal) 3133 wheelHorizontal = aWheelDelta / 120; 3134 3135 if (mMouseCaptured) 3136 { 3137 #ifdef Q_WS_WIN32 3138 /* send pending WM_PAINT events */ 3139 ::UpdateWindow (viewport()->winId()); 3140 #endif 3141 3142 CMouse mouse = mConsole.GetMouse(); 3143 mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(), 3144 aGlobalPos.y() - mLastPos.y(), 3145 wheelVertical, wheelHorizontal, state); 3146 3147 #if defined (Q_WS_MAC) 3148 /* 3149 * Keep the mouse from leaving the widget. 3150 * 3151 * This is a bit tricky to get right because if it escapes we won't necessarily 3152 * get mouse events any longer and can warp it back. So, we keep safety zone 3153 * of up to 300 pixels around the borders of the widget to prevent this from 3154 * happening. Also, the mouse is warped back to the center of the widget. 3155 * 3156 * (Note, aPos seems to be unreliable, it caused endless recursion here at one points...) 3157 * (Note, synergy and other remote clients might not like this cursor warping.) 3158 */ 3159 QRect rect = viewport()->visibleRegion().boundingRect(); 3160 QPoint pw = viewport()->mapToGlobal (viewport()->pos()); 3161 rect.translate (pw.x(), pw.y()); 3162 3163 QRect dpRect = QApplication::desktop()->screenGeometry (viewport()); 3164 if (rect.intersects (dpRect)) 3165 rect = rect.intersect (dpRect); 3166 3167 int wsafe = rect.width() / 6; 3168 rect.setWidth (rect.width() - wsafe * 2); 3169 rect.setLeft (rect.left() + wsafe); 3170 3171 int hsafe = rect.height() / 6; 3172 rect.setWidth (rect.height() - hsafe * 2); 3173 rect.setTop (rect.top() + hsafe); 3174 3175 if (rect.contains (aGlobalPos, true)) 3176 mLastPos = aGlobalPos; 3177 else 3178 { 3179 mLastPos = rect.center(); 3180 QCursor::setPos (mLastPos); 3181 } 3182 3183 #else /* !Q_WS_MAC */ 3184 3185 /* "jerk" the mouse by bringing it to the opposite side 3186 * to simulate the endless moving */ 3187 3188 #ifdef Q_WS_WIN32 3189 int we = viewport()->width() - 1; 3190 int he = viewport()->height() - 1; 3191 QPoint p = aPos; 3192 if (aPos.x() == 0) 3193 p.setX (we - 1); 3194 else if (aPos.x() == we) 3195 p.setX (1); 3196 if (aPos.y() == 0 ) 3197 p.setY (he - 1); 3198 else if (aPos.y() == he) 3199 p.setY (1); 3200 3201 if (p != aPos) 3202 { 3203 mLastPos = viewport()->mapToGlobal (p); 3204 QCursor::setPos (mLastPos); 3205 } 3206 else 3207 { 3208 mLastPos = aGlobalPos; 3209 } 3210 #else 3211 int we = QApplication::desktop()->width() - 1; 3212 int he = QApplication::desktop()->height() - 1; 3213 QPoint p = aGlobalPos; 3214 if (aGlobalPos.x() == 0) 3215 p.setX (we - 1); 3216 else if (aGlobalPos.x() == we) 3217 p.setX( 1 ); 3218 if (aGlobalPos.y() == 0) 3219 p.setY (he - 1); 3220 else if (aGlobalPos.y() == he) 3221 p.setY (1); 3222 3223 if (p != aGlobalPos) 3224 { 3225 mLastPos = p; 3226 QCursor::setPos (mLastPos); 3227 } 3228 else 3229 { 3230 mLastPos = aGlobalPos; 3231 } 3232 #endif 3233 #endif /* !Q_WS_MAC */ 3234 return true; /* stop further event handling */ 3235 } 3236 else /* !mMouseCaptured */ 3237 { 3238 if (mMainWnd->isTrueFullscreen()) 3239 { 3240 if (mode != VBoxDefs::SDLMode) 3241 { 3242 /* try to automatically scroll the guest canvas if the 3243 * mouse is on the screen border */ 3244 /// @todo (r=dmik) better use a timer for autoscroll 3245 QRect scrGeo = QApplication::desktop()->screenGeometry (this); 3246 int dx = 0, dy = 0; 3247 if (scrGeo.width() < contentsWidth()) 3248 { 3249 if (scrGeo.left() == aGlobalPos.x()) dx = -1; 3250 if (scrGeo.right() == aGlobalPos.x()) dx = +1; 3251 } 3252 if (scrGeo.height() < contentsHeight()) 3253 { 3254 if (scrGeo.top() == aGlobalPos.y()) dy = -1; 3255 if (scrGeo.bottom() == aGlobalPos.y()) dy = +1; 3256 } 3257 if (dx || dy) 3258 scrollBy (dx, dy); 3259 } 3260 } 3261 3262 if (mMouseAbsolute && mMouseIntegration) 3263 { 3264 int cw = contentsWidth(), ch = contentsHeight(); 3265 int vw = visibleWidth(), vh = visibleHeight(); 3266 3267 if (mode != VBoxDefs::SDLMode) 3268 { 3269 /* try to automatically scroll the guest canvas if the 3270 * mouse goes outside its visible part */ 3271 3272 int dx = 0; 3273 if (aPos.x() > vw) dx = aPos.x() - vw; 3274 else if (aPos.x() < 0) dx = aPos.x(); 3275 int dy = 0; 3276 if (aPos.y() > vh) dy = aPos.y() - vh; 3277 else if (aPos.y() < 0) dy = aPos.y(); 3278 if (dx != 0 || dy != 0) scrollBy (dx, dy); 3279 } 3280 3281 QPoint cpnt = viewportToContents (aPos); 3282 if (cpnt.x() < 0) cpnt.setX (0); 3283 else if (cpnt.x() > cw) cpnt.setX (cw); 3284 if (cpnt.y() < 0) cpnt.setY (0); 3285 else if (cpnt.y() > ch) cpnt.setY (ch); 3286 3287 CMouse mouse = mConsole.GetMouse(); 3288 mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical, 3289 wheelHorizontal, state); 3290 return true; /* stop further event handling */ 3291 } 3292 else 3293 { 3294 if (hasFocus() && 3295 (aType == QEvent::MouseButtonRelease && 3296 aButtons == Qt::NoButton)) 3297 { 3298 if (isPaused()) 3299 { 3300 vboxProblem().remindAboutPausedVMInput(); 3301 } 3302 else if (isRunning()) 3303 { 3304 /* temporarily disable auto capture that will take 3305 * place after this dialog is dismissed because 3306 * the capture state is to be defined by the 3307 * dialog result itself */ 3308 mDisableAutoCapture = true; 3309 bool autoConfirmed = false; 3310 bool ok = vboxProblem().confirmInputCapture (&autoConfirmed); 3311 if (autoConfirmed) 3312 mDisableAutoCapture = false; 3313 /* otherwise, the disable flag will be reset in 3314 * the next console view's foucs in event (since 3315 * may happen asynchronously on some platforms, 3316 * after we return from this code) */ 3317 3318 if (ok) 3319 { 3320 #ifdef Q_WS_X11 3321 /* make sure that pending FocusOut events from the 3322 * previous message box are handled, otherwise the 3323 * mouse is immediately ungrabbed again */ 3324 qApp->processEvents(); 3325 #endif 3326 captureKbd (true); 3327 captureMouse (true); 3328 } 3329 } 3330 } 3331 } 3332 } 3333 3334 return false; 3335 } 3336 3337 void VBoxConsoleView::onStateChange (KMachineState state) 3338 { 3339 switch (state) 3340 { 3341 case KMachineState_Paused: 3342 case KMachineState_TeleportingPausedVM: 3343 { 3344 if ( mode != VBoxDefs::TimerMode 3345 && mFrameBuf 3346 && ( state != KMachineState_TeleportingPausedVM 3347 || mLastState != KMachineState_Teleporting) 3348 ) 3349 { 3350 /* 3351 * Take a screen snapshot. Note that TakeScreenShot() always 3352 * needs a 32bpp image 3353 */ 3354 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32); 3355 CDisplay dsp = mConsole.GetDisplay(); 3356 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 3357 /* 3358 * TakeScreenShot() may fail if, e.g. the Paused notification 3359 * was delivered after the machine execution was resumed. It's 3360 * not fatal. 3361 */ 3362 if (dsp.isOk()) 3363 { 3364 dimImage (shot); 3365 mPausedShot = QPixmap::fromImage (shot); 3366 /* fully repaint to pick up mPausedShot */ 3367 repaint(); 3368 } 3369 } 3370 /* fall through */ 3371 } 3372 case KMachineState_Stuck: 3373 { 3374 /* reuse the focus event handler to uncapture everything */ 3375 if (hasFocus()) 3376 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */); 3377 break; 3378 } 3379 case KMachineState_Running: 3380 { 3381 if ( mLastState == KMachineState_Paused 3382 || mLastState == KMachineState_TeleportingPausedVM 3383 ) 3384 { 3385 if (mode != VBoxDefs::TimerMode && mFrameBuf) 3386 { 3387 /* reset the pixmap to free memory */ 3388 mPausedShot = QPixmap (); 3389 /* 3390 * ask for full guest display update (it will also update 3391 * the viewport through IFramebuffer::NotifyUpdate) 3392 */ 3393 CDisplay dsp = mConsole.GetDisplay(); 3394 dsp.InvalidateAndUpdate(); 3395 } 3396 } 3397 /* reuse the focus event handler to capture input */ 3398 if (hasFocus()) 3399 focusEvent (true /* aHasFocus */); 3400 break; 3401 } 3402 default: 3403 break; 3404 } 3405 3406 mLastState = state; 3407 } 3408 3409 void VBoxConsoleView::doRefresh() 3410 { 3411 viewport()->repaint(); 3412 } 3413 3414 void VBoxConsoleView::resizeEvent (QResizeEvent *) 3415 { 3416 updateSliders(); 3417 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 3418 QRect r = viewport()->geometry(); 3419 // printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height()); 3420 PostBoundsChanged (r); 3421 #endif /* Q_WS_MAC */ 3422 } 3423 3424 void VBoxConsoleView::moveEvent (QMoveEvent *) 3425 { 3426 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 3427 QRect r = viewport()->geometry(); 3428 // printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height()); 3429 PostBoundsChanged (r); 3430 #endif /* Q_WS_MAC */ 3431 } 3432 3433 void VBoxConsoleView::paintEvent (QPaintEvent *pe) 3434 { 3435 if (mPausedShot.isNull()) 3436 { 3437 /* delegate the paint function to the VBoxFrameBuffer interface */ 3438 if (mFrameBuf) 3439 mFrameBuf->paintEvent (pe); 3440 #ifdef Q_WS_MAC 3441 /* Update the dock icon if we are in the running state */ 3442 if (isRunning()) 3443 updateDockIcon(); 3444 #endif 3445 return; 3446 } 3447 3448 #ifdef VBOX_GUI_USE_QUARTZ2D 3449 if (mode == VBoxDefs::Quartz2DMode && mFrameBuf) 3450 { 3451 mFrameBuf->paintEvent (pe); 3452 updateDockIcon(); 3453 } 3454 else 3455 #endif 3456 { 3457 /* we have a snapshot for the paused state */ 3458 QRect r = pe->rect().intersect (viewport()->rect()); 3459 /* We have to disable paint on screen if we are using the regular painter */ 3460 bool paintOnScreen = viewport()->testAttribute (Qt::WA_PaintOnScreen); 3461 viewport()->setAttribute (Qt::WA_PaintOnScreen, false); 3462 QPainter pnt (viewport()); 3463 pnt.drawPixmap (r.x(), r.y(), mPausedShot, 3464 r.x() + contentsX(), r.y() + contentsY(), 3465 r.width(), r.height()); 3466 /* Restore the attribute to its previous state */ 3467 viewport()->setAttribute (Qt::WA_PaintOnScreen, paintOnScreen); 3468 #ifdef Q_WS_MAC 3469 updateDockIcon(); 3470 #endif 3471 } 3472 3473 } 3474 3475 /** 3476 * Captures the keyboard. When captured, no keyboard input reaches the host 3477 * system (including most system combinations like Alt-Tab). 3478 * 3479 * @param aCapture true to capture, false to uncapture. 3480 * @param aEmitSignal Whether to emit keyboardStateChanged() or not. 3481 */ 3482 void VBoxConsoleView::captureKbd (bool aCapture, bool aEmitSignal /* = true */) 3483 { 3484 AssertMsg (mAttached, ("Console must be attached")); 3485 3486 if (mKbdCaptured == aCapture) 3487 return; 3488 3489 /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is 3490 * used instead. On X11, we use XGrabKey instead of XGrabKeyboard (called 3491 * by QWidget::grabKeyboard()) because the latter causes problems under 3492 * metacity 2.16 (in particular, due to a bug, a window cannot be moved 3493 * using the mouse if it is currently grabing the keyboard). On Mac OS X, 3494 * we use the Qt methods + disabling global hot keys + watching modifiers 3495 * (for right/left separation). */ 3496 #if defined (Q_WS_WIN32) 3497 /**/ 3498 #elif defined (Q_WS_X11) 3499 if (aCapture) 3500 XGrabKey (QX11Info::display(), AnyKey, AnyModifier, 3501 window()->winId(), False, 3502 GrabModeAsync, GrabModeAsync); 3503 else 3504 XUngrabKey (QX11Info::display(), AnyKey, AnyModifier, 3505 window()->winId()); 3506 #elif defined (Q_WS_MAC) 3507 if (aCapture) 3508 { 3509 ::DarwinDisableGlobalHotKeys (true); 3510 grabKeyboard(); 3511 } 3512 else 3513 { 3514 ::DarwinDisableGlobalHotKeys (false); 3515 releaseKeyboard(); 3516 } 3517 #else 3518 if (aCapture) 3519 grabKeyboard(); 3520 else 3521 releaseKeyboard(); 3522 #endif 3523 3524 mKbdCaptured = aCapture; 3525 3526 if (aEmitSignal) 3527 emitKeyboardStateChanged(); 3528 } 3529 3530 /** 3531 * Captures the host mouse pointer. When captured, the mouse pointer is 3532 * unavailable to the host applications. 3533 * 3534 * @param aCapture true to capture, false to uncapture. 3535 * @param aEmitSignal Whether to emit mouseStateChanged() or not. 3536 */ 3537 void VBoxConsoleView::captureMouse (bool aCapture, bool aEmitSignal /* = true */) 3538 { 3539 AssertMsg (mAttached, ("Console must be attached")); 3540 3541 if (mMouseCaptured == aCapture) 3542 return; 3543 3544 if (aCapture) 3545 { 3546 /* memorize the host position where the cursor was captured */ 3547 mCapturedPos = QCursor::pos(); 3548 #ifdef Q_WS_WIN32 3549 viewport()->setCursor (QCursor (Qt::BlankCursor)); 3550 /* move the mouse to the center of the visible area */ 3551 QCursor::setPos (mapToGlobal (visibleRegion().boundingRect().center())); 3552 mLastPos = QCursor::pos(); 3553 #elif defined (Q_WS_MAC) 3554 /* move the mouse to the center of the visible area */ 3555 mLastPos = mapToGlobal (visibleRegion().boundingRect().center()); 3556 QCursor::setPos (mLastPos); 3557 /* grab all mouse events. */ 3558 viewport()->grabMouse(); 3559 #else 3560 viewport()->grabMouse(); 3561 mLastPos = QCursor::pos(); 3562 #endif 3563 } 3564 else 3565 { 3566 #ifndef Q_WS_WIN32 3567 viewport()->releaseMouse(); 3568 #endif 3569 /* release mouse buttons */ 3570 CMouse mouse = mConsole.GetMouse(); 3571 mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0); 3572 } 3573 3574 mMouseCaptured = aCapture; 3575 3576 updateMouseClipping(); 3577 3578 if (aEmitSignal) 3579 emitMouseStateChanged(); 3580 } 3581 3582 /** 3583 * Searches for a menu item with a given hot key (shortcut). If the item 3584 * is found, activates it and returns true. Otherwise returns false. 3585 */ 3586 bool VBoxConsoleView::processHotKey (const QKeySequence &aKey, 3587 const QList <QAction*> &aData) 3588 { 3589 foreach (QAction *pAction, aData) 3590 { 3591 if (QMenu *menu = pAction->menu()) 3592 { 3593 /* Process recursively for each sub-menu */ 3594 if (processHotKey (aKey, menu->actions())) 3595 return true; 3596 } 3597 else 3598 { 3599 QString hotkey = VBoxGlobal::extractKeyFromActionText (pAction->text()); 3600 if (pAction->isEnabled() && !hotkey.isEmpty()) 3601 { 3602 if (aKey.matches (QKeySequence (hotkey)) == QKeySequence::ExactMatch) 3603 { 3604 /* We asynchronously post a special event instead of calling 3605 * pAction->trigger() directly, to let key presses and 3606 * releases be processed correctly by Qt first. 3607 * Note: we assume that nobody will delete the menu item 3608 * corresponding to the key sequence, so that the pointer to 3609 * menu data posted along with the event will remain valid in 3610 * the event handler, at least until the main window is closed. */ 3611 QApplication::postEvent (this, new ActivateMenuEvent (pAction)); 3612 return true; 3613 } 3614 } 3615 } 3616 } 3617 3618 return false; 3619 } 3620 3621 /** 3622 * Send the KEY BREAK code to the VM for all currently pressed keys. 3623 * 3624 * @param aReleaseHostKey @c true to set the host key state to unpressed. 3625 */ 3626 void VBoxConsoleView::releaseAllPressedKeys (bool aReleaseHostKey /* = true*/) 3627 { 3628 AssertMsg (mAttached, ("Console must be attached")); 3629 3630 CKeyboard keyboard = mConsole.GetKeyboard(); 3631 bool fSentRESEND = false; 3632 3633 /* send a dummy scan code (RESEND) to prevent the guest OS from recognizing 3634 * a single key click (for ex., Alt) and performing an unwanted action 3635 * (for ex., activating the menu) when we release all pressed keys below. 3636 * Note, that it's just a guess that sending RESEND will give the desired 3637 * effect :), but at least it works with NT and W2k guests. */ 3638 3639 /// @todo Sending 0xFE is responsible for the warning 3640 // 3641 // ``atkbd.c: Spurious NAK on isa0060/serio0. Some program might 3642 // be trying access hardware directly'' 3643 // 3644 // on Linux guests (#1944). It might also be responsible for #1949. Don't 3645 // send this command unless we really have to release any key modifier. 3646 // --frank 3647 3648 for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++) 3649 { 3650 if (mPressedKeys [i] & IsKeyPressed) 3651 { 3652 if (!fSentRESEND) 3653 { 3654 keyboard.PutScancode (0xFE); 3655 fSentRESEND = true; 3656 } 3657 keyboard.PutScancode (i | 0x80); 3658 } 3659 else if (mPressedKeys [i] & IsExtKeyPressed) 3660 { 3661 if (!fSentRESEND) 3662 { 3663 keyboard.PutScancode (0xFE); 3664 fSentRESEND = true; 3665 } 3666 QVector <LONG> codes (2); 3667 codes[0] = 0xE0; 3668 codes[1] = i | 0x80; 3669 keyboard.PutScancodes (codes); 3670 } 3671 mPressedKeys [i] = 0; 3672 } 3673 3674 if (aReleaseHostKey) 3675 mIsHostkeyPressed = false; 3676 3677 #ifdef Q_WS_MAC 3678 /* clear most of the modifiers. */ 3679 mDarwinKeyModifiers &= 3680 alphaLock | kEventKeyModifierNumLockMask | 3681 (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (gs.hostKey())); 3682 #endif 3683 3684 emitKeyboardStateChanged(); 3685 } 3686 3687 void VBoxConsoleView::saveKeyStates() 3688 { 3689 ::memcpy (mPressedKeysCopy, mPressedKeys, sizeof (mPressedKeys)); 3690 } 3691 3692 void VBoxConsoleView::sendChangedKeyStates() 3693 { 3694 AssertMsg (mAttached, ("Console must be attached")); 3695 3696 QVector <LONG> codes (2); 3697 CKeyboard keyboard = mConsole.GetKeyboard(); 3698 for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); ++ i) 3699 { 3700 uint8_t os = mPressedKeysCopy [i]; 3701 uint8_t ns = mPressedKeys [i]; 3702 if ((os & IsKeyPressed) != (ns & IsKeyPressed)) 3703 { 3704 codes [0] = i; 3705 if (!(ns & IsKeyPressed)) 3706 codes[0] |= 0x80; 3707 keyboard.PutScancode (codes[0]); 3708 } 3709 else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed)) 3710 { 3711 codes [0] = 0xE0; 3712 codes [1] = i; 3713 if (!(ns & IsExtKeyPressed)) 3714 codes [1] |= 0x80; 3715 keyboard.PutScancodes (codes); 3716 } 3717 } 3718 } 3719 3720 void VBoxConsoleView::updateMouseClipping() 3721 { 3722 AssertMsg (mAttached, ("Console must be attached")); 3723 3724 if (mMouseCaptured) 3725 { 3726 viewport()->setCursor (QCursor (Qt::BlankCursor)); 3727 #ifdef Q_WS_WIN32 3728 QRect r = viewport()->rect(); 3729 r.moveTopLeft (viewport()->mapToGlobal (QPoint (0, 0))); 3730 RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 }; 3731 ::ClipCursor (&rect); 3732 #endif 3733 } 3734 else 3735 { 3736 #ifdef Q_WS_WIN32 3737 ::ClipCursor (NULL); 3738 #endif 3739 /* return the cursor to where it was when we captured it and show it */ 3740 QCursor::setPos (mCapturedPos); 3741 viewport()->unsetCursor(); 3742 } 3743 } 3744 3745 void VBoxConsoleView::setPointerShape (MousePointerChangeEvent *me) 3746 { 3747 if (me->shapeData() != NULL) 3748 { 3749 bool ok = false; 3750 3751 const uchar *srcAndMaskPtr = me->shapeData(); 3752 uint andMaskSize = (me->width() + 7) / 8 * me->height(); 3753 const uchar *srcShapePtr = me->shapeData() + ((andMaskSize + 3) & ~3); 3754 uint srcShapePtrScan = me->width() * 4; 3755 3756 #if defined (Q_WS_WIN) 3757 3758 BITMAPV5HEADER bi; 3759 HBITMAP hBitmap; 3760 void *lpBits; 3761 3762 ::ZeroMemory (&bi, sizeof (BITMAPV5HEADER)); 3763 bi.bV5Size = sizeof (BITMAPV5HEADER); 3764 bi.bV5Width = me->width(); 3765 bi.bV5Height = - (LONG) me->height(); 3766 bi.bV5Planes = 1; 3767 bi.bV5BitCount = 32; 3768 bi.bV5Compression = BI_BITFIELDS; 3769 // specifiy a supported 32 BPP alpha format for Windows XP 3770 bi.bV5RedMask = 0x00FF0000; 3771 bi.bV5GreenMask = 0x0000FF00; 3772 bi.bV5BlueMask = 0x000000FF; 3773 if (me->hasAlpha()) 3774 bi.bV5AlphaMask = 0xFF000000; 3775 else 3776 bi.bV5AlphaMask = 0; 3777 3778 HDC hdc = GetDC (NULL); 3779 3780 // create the DIB section with an alpha channel 3781 hBitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS, 3782 (void **) &lpBits, NULL, (DWORD) 0); 3783 3784 ReleaseDC (NULL, hdc); 3785 3786 HBITMAP hMonoBitmap = NULL; 3787 if (me->hasAlpha()) 3788 { 3789 // create an empty mask bitmap 3790 hMonoBitmap = CreateBitmap (me->width(), me->height(), 1, 1, NULL); 3791 } 3792 else 3793 { 3794 /* Word aligned AND mask. Will be allocated and created if necessary. */ 3795 uint8_t *pu8AndMaskWordAligned = NULL; 3796 3797 /* Width in bytes of the original AND mask scan line. */ 3798 uint32_t cbAndMaskScan = (me->width() + 7) / 8; 3799 3800 if (cbAndMaskScan & 1) 3801 { 3802 /* Original AND mask is not word aligned. */ 3803 3804 /* Allocate memory for aligned AND mask. */ 3805 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ ((cbAndMaskScan + 1) * me->height()); 3806 3807 Assert(pu8AndMaskWordAligned); 3808 3809 if (pu8AndMaskWordAligned) 3810 { 3811 /* According to MSDN the padding bits must be 0. 3812 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. 3813 */ 3814 uint32_t u32PaddingBits = cbAndMaskScan * 8 - me->width(); 3815 Assert(u32PaddingBits < 8); 3816 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 3817 3818 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 3819 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, me->width(), cbAndMaskScan)); 3820 3821 uint8_t *src = (uint8_t *)srcAndMaskPtr; 3822 uint8_t *dst = pu8AndMaskWordAligned; 3823 3824 unsigned i; 3825 for (i = 0; i < me->height(); i++) 3826 { 3827 memcpy (dst, src, cbAndMaskScan); 3828 3829 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; 3830 3831 src += cbAndMaskScan; 3832 dst += cbAndMaskScan + 1; 3833 } 3834 } 3835 } 3836 3837 /* create the AND mask bitmap */ 3838 hMonoBitmap = ::CreateBitmap (me->width(), me->height(), 1, 1, 3839 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 3840 3841 if (pu8AndMaskWordAligned) 3842 { 3843 RTMemTmpFree (pu8AndMaskWordAligned); 3844 } 3845 } 3846 3847 Assert (hBitmap); 3848 Assert (hMonoBitmap); 3849 if (hBitmap && hMonoBitmap) 3850 { 3851 DWORD *dstShapePtr = (DWORD *) lpBits; 3852 3853 for (uint y = 0; y < me->height(); y ++) 3854 { 3855 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 3856 srcShapePtr += srcShapePtrScan; 3857 dstShapePtr += me->width(); 3858 } 3859 3860 ICONINFO ii; 3861 ii.fIcon = FALSE; 3862 ii.xHotspot = me->xHot(); 3863 ii.yHotspot = me->yHot(); 3864 ii.hbmMask = hMonoBitmap; 3865 ii.hbmColor = hBitmap; 3866 3867 HCURSOR hAlphaCursor = CreateIconIndirect (&ii); 3868 Assert (hAlphaCursor); 3869 if (hAlphaCursor) 3870 { 3871 viewport()->setCursor (QCursor (hAlphaCursor)); 3872 ok = true; 3873 if (mAlphaCursor) 3874 DestroyIcon (mAlphaCursor); 3875 mAlphaCursor = hAlphaCursor; 3876 } 3877 } 3878 3879 if (hMonoBitmap) 3880 DeleteObject (hMonoBitmap); 3881 if (hBitmap) 3882 DeleteObject (hBitmap); 3883 3884 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 3885 3886 XcursorImage *img = XcursorImageCreate (me->width(), me->height()); 3887 Assert (img); 3888 if (img) 3889 { 3890 img->xhot = me->xHot(); 3891 img->yhot = me->yHot(); 3892 3893 XcursorPixel *dstShapePtr = img->pixels; 3894 3895 for (uint y = 0; y < me->height(); y ++) 3896 { 3897 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 3898 3899 if (!me->hasAlpha()) 3900 { 3901 /* convert AND mask to the alpha channel */ 3902 uchar byte = 0; 3903 for (uint x = 0; x < me->width(); x ++) 3904 { 3905 if (!(x % 8)) 3906 byte = *(srcAndMaskPtr ++); 3907 else 3908 byte <<= 1; 3909 3910 if (byte & 0x80) 3911 { 3912 /* Linux doesn't support inverted pixels (XOR ops, 3913 * to be exact) in cursor shapes, so we detect such 3914 * pixels and always replace them with black ones to 3915 * make them visible at least over light colors */ 3916 if (dstShapePtr [x] & 0x00FFFFFF) 3917 dstShapePtr [x] = 0xFF000000; 3918 else 3919 dstShapePtr [x] = 0x00000000; 3920 } 3921 else 3922 dstShapePtr [x] |= 0xFF000000; 3923 } 3924 } 3925 3926 srcShapePtr += srcShapePtrScan; 3927 dstShapePtr += me->width(); 3928 } 3929 3930 Cursor cur = XcursorImageLoadCursor (QX11Info::display(), img); 3931 Assert (cur); 3932 if (cur) 3933 { 3934 viewport()->setCursor (QCursor (cur)); 3935 ok = true; 3936 } 3937 3938 XcursorImageDestroy (img); 3939 } 3940 3941 #elif defined(Q_WS_MAC) 3942 3943 /* Create a ARGB image out of the shape data. */ 3944 QImage image (me->width(), me->height(), QImage::Format_ARGB32); 3945 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 3946 unsigned cbSrcMaskLine = RT_ALIGN (me->width(), 8) / 8; 3947 for (unsigned int y = 0; y < me->height(); ++y) 3948 { 3949 for (unsigned int x = 0; x < me->width(); ++x) 3950 { 3951 unsigned int color = ((unsigned int*)srcShapePtr)[y*me->width()+x]; 3952 /* If the alpha channel isn't in the shape data, we have to 3953 * create them from the and-mask. This is a bit field where 1 3954 * represent transparency & 0 opaque respectively. */ 3955 if (!me->hasAlpha()) 3956 { 3957 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) 3958 color |= 0xff000000; 3959 else 3960 { 3961 /* This isn't quite right, but it's the best we can do I 3962 * think... */ 3963 if (color & 0x00ffffff) 3964 color = 0xff000000; 3965 else 3966 color = 0x00000000; 3967 } 3968 } 3969 image.setPixel (x, y, color); 3970 } 3971 /* Move one scanline forward. */ 3972 pbSrcMask += cbSrcMaskLine; 3973 } 3974 /* Set the new cursor */ 3975 QCursor cursor (QPixmap::fromImage (image), 3976 me->xHot(), me->yHot()); 3977 viewport()->setCursor (cursor); 3978 ok = true; 3979 NOREF (srcShapePtrScan); 3980 3981 #else 3982 3983 # warning "port me" 3984 3985 #endif 3986 if (ok) 3987 mLastCursor = viewport()->cursor(); 3988 else 3989 viewport()->unsetCursor(); 3990 } 3991 else 3992 { 3993 /* 3994 * We did not get any shape data 3995 */ 3996 if (me->isVisible()) 3997 { 3998 viewport()->setCursor (mLastCursor); 3999 } 4000 else 4001 { 4002 viewport()->setCursor (Qt::BlankCursor); 4003 } 4004 } 4005 mHideHostPointer = !me->isVisible(); 4006 } 4007 4008 inline QRgb qRgbIntensity (QRgb rgb, int mul, int div) 4009 { 4010 int r = qRed (rgb); 4011 int g = qGreen (rgb); 4012 int b = qBlue (rgb); 4013 return qRgb (mul * r / div, mul * g / div, mul * b / div); 4014 } 4015 4016 /* static */ 4017 void VBoxConsoleView::dimImage (QImage &img) 4018 { 4019 for (int y = 0; y < img.height(); y ++) { 4020 if (y % 2) { 4021 if (img.depth() == 32) { 4022 for (int x = 0; x < img.width(); x ++) { 4023 int gray = qGray (img.pixel (x, y)) / 2; 4024 img.setPixel (x, y, qRgb (gray, gray, gray)); 4025 // img.setPixel (x, y, qRgbIntensity (img.pixel (x, y), 1, 2)); 4026 } 4027 } else { 4028 ::memset (img.scanLine (y), 0, img.bytesPerLine()); 4029 } 4030 } else { 4031 if (img.depth() == 32) { 4032 for (int x = 0; x < img.width(); x ++) { 4033 int gray = (2 * qGray (img.pixel (x, y))) / 3; 4034 img.setPixel (x, y, qRgb (gray, gray, gray)); 4035 // img.setPixel (x, y, qRgbIntensity (img.pixel(x, y), 2, 3)); 4036 } 4037 } 4038 } 4039 } 4040 } 4041 4042 void VBoxConsoleView::doResizeHint (const QSize &aToSize) 4043 { 4044 if (mGuestSupportsGraphics && mAutoresizeGuest) 121 #if 0 // TODO: fix that logic! 122 if (m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled) 4045 123 { 4046 124 /* If this slot is invoked directly then use the passed size … … 4048 126 * We assume here that the centralWidget() contains this view only 4049 127 * and gives it all available space. */ 4050 QSize sz (aToSize.isValid() ? aToSize : mMainWnd->centralWidget()->size());4051 if (! aToSize.isValid())4052 sz -= QSize 128 QSize sz(toSize.isValid() ? toSize : machineWindow()->centralWidget()->size()); 129 if (!toSize.isValid()) 130 sz -= QSize(frameWidth() * 2, frameWidth() * 2); 4053 131 /* Do not send out useless hints. */ 4054 if ((sz.width() == mStoredConsoleSize.width()) && 4055 (sz.height() == mStoredConsoleSize.height())) 132 if ((sz.width() == mStoredConsoleSize.width()) && (sz.height() == mStoredConsoleSize.height())) 4056 133 return; 4057 134 /* We only actually send the hint if … … 4062 139 * needed (e.g. the autoresize was just enabled and the console 4063 140 * was resized while it was disabled). */ 4064 if (mAutoresizeGuest && 4065 (aToSize.isValid() || mDoResize)) 141 if (m_bIsGuestAutoresizeEnabled && (toSize.isValid() || mDoResize)) 4066 142 { 4067 LogFlowFunc (("Will suggest %d x %d\n", sz.width(), sz.height())); 143 /* Remember the new size. */ 144 storeConsoleSize(sz.width(), sz.height()); 4068 145 4069 /* Remember the new size. */ 4070 storeConsoleSize (sz.width(), sz.height()); 4071 4072 mConsole.GetDisplay().SetVideoModeHint (sz.width(), sz.height(), 0, 0); 146 mConsole.GetDisplay().SetVideoModeHint(sz.width(), sz.height(), 0, 0); 4073 147 } 4074 /* we have resized now... */148 /* We have resized now... */ 4075 149 mDoResize = false; 4076 150 } 151 #endif 4077 152 } 4078 153 4079 4080 154 /* If the desktop geometry is set automatically, this will update it. */ 4081 void VBoxConsoleView::doResizeDesktop(int)155 void UIMachineViewNormal::doResizeDesktop(int) 4082 156 { 4083 157 calculateDesktopGeometry(); 4084 158 } 4085 159 4086 /** 4087 * Store the current size of the console (i.e. the viewport to the guest). 4088 * This has two purposes. One is to suppress unwanted resize events for 4089 * which the new size is the same as the stored size. The other is to expand 4090 * the maximum size to which we will let the guest resize itself. It makes 4091 * no sense to forbid guest resizes which are less than the current resolution 4092 * anyway. 4093 * 4094 * @param aWidth width of the resolution hint 4095 * @param aHeight height of the resolution hint 4096 */ 4097 void VBoxConsoleView::storeConsoleSize (int aWidth, int aHeight) 160 void UIMachineViewNormal::sltToggleGuestAutoresize(bool bOn) 4098 161 { 4099 LogFlowThisFunc (("aWidth=%d, aHeight=%d\n", aWidth, aHeight));4100 mStoredConsoleSize = QRect (0, 0, aWidth, aHeight);4101 } 162 if (m_bIsGuestAutoresizeEnabled != bOn) 163 { 164 m_bIsGuestAutoresizeEnabled = bOn; 4102 165 4103 /** 4104 * Do initial setup of desktop geometry restrictions on the guest framebuffer. 4105 * These determine the maximum size the guest framebuffer can take on. 4106 * 4107 * @note a hint from the host will always override these restrictions. 4108 * 4109 * @param aGeo Fixed - the guest has a fixed maximum framebuffer size 4110 * Automatic - we calculate the maximum size ourselves. The 4111 * calculations will not actually be done until 4112 * @a calculateDesktopGeometry is called, since 4113 * we don't initially have the information needed. 4114 * Any - any size is allowed 4115 * @param aWidth The maximum width for the guest screen or zero for no change 4116 * (only used for fixed geometry) 4117 * @param aHeight The maximum height for the guest screen or zero for no change 4118 * (only used for fixed geometry) 4119 */ 4120 void VBoxConsoleView::setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight) 4121 { 4122 LogFlowThisFunc (("aGeo=%s, aWidth=%d, aHeight=%d\n", 4123 (aGeo == DesktopGeo_Fixed ? "Fixed" : 4124 aGeo == DesktopGeo_Automatic ? "Automatic" : 4125 aGeo == DesktopGeo_Any ? "Any" : "Invalid"), 4126 aWidth, aHeight)); 4127 switch (aGeo) 4128 { 4129 case DesktopGeo_Fixed: 4130 mDesktopGeo = DesktopGeo_Fixed; 4131 if (aWidth != 0 && aHeight != 0) 4132 mDesktopGeometry = QRect (0, 0, aWidth, aHeight); 4133 else 4134 mDesktopGeometry = QRect (0, 0, 0, 0); 4135 storeConsoleSize (0, 0); 4136 break; 4137 case DesktopGeo_Automatic: 4138 mDesktopGeo = DesktopGeo_Automatic; 4139 mDesktopGeometry = QRect (0, 0, 0, 0); 4140 storeConsoleSize (0, 0); 4141 break; 4142 case DesktopGeo_Any: 4143 mDesktopGeo = DesktopGeo_Any; 4144 mDesktopGeometry = QRect (0, 0, 0, 0); 4145 break; 4146 default: 4147 AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo)); 4148 mDesktopGeo = DesktopGeo_Invalid; 166 maybeRestrictMinimumSize(); 167 168 if (m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled) 169 doResizeHint(); 4149 170 } 4150 171 } 4151 172 4152 4153 /** 4154 * If we are in automatic mode, the geometry restrictions will be recalculated. 4155 * This is needed in particular on the first widget resize, as we can't 4156 * calculate them correctly before that. 4157 * 4158 * @note a hint from the host will always override these restrictions. 4159 * @note we can't do calculations on the fly when they are needed, because 4160 * they require querying the X server on X11 hosts and this must be done 4161 * from within the GUI thread, due to the single threadedness of Xlib. 4162 */ 4163 void VBoxConsoleView::calculateDesktopGeometry() 173 void UIMachineViewNormal::sltAdditionsStateChanged(const QString & /* strVersion */, bool /* bIsActive */, 174 bool /* bIsSeamlessSupported */, bool bIsGraphicsSupported) 4164 175 { 4165 LogFlowThisFunc (("Entering\n")); 4166 /* This method should not get called until we have initially set up the */ 4167 Assert ((mDesktopGeo != DesktopGeo_Invalid)); 4168 /* If we are not doing automatic geometry calculation then there is 4169 * nothing to do. */ 4170 if (DesktopGeo_Automatic == mDesktopGeo) 4171 { 4172 /* Available geometry of the desktop. If the desktop is a single 4173 * screen, this will exclude space taken up by desktop taskbars 4174 * and things, but this is unfortunately not true for the more 4175 * complex case of a desktop spanning multiple screens. */ 4176 QRect desktop = availableGeometry(); 4177 /* The area taken up by the console window on the desktop, 4178 * including window frame, title and menu bar and whatnot. */ 4179 QRect frame = mMainWnd->frameGeometry(); 4180 /* The area taken up by the console window, minus all 4181 * decorations. */ 4182 QRect window = mMainWnd->centralWidget()->geometry(); 4183 /* To work out how big we can make the console window while still 4184 * fitting on the desktop, we calculate desktop - frame + window. 4185 * This works because the difference between frame and window 4186 * (or at least its width and height) is a constant. */ 4187 mDesktopGeometry = 4188 QRect (0, 0, desktop.width() - frame.width() + window.width(), 4189 desktop.height() - frame.height() + window.height()); 4190 LogFlowThisFunc (("Setting %d, %d\n", mDesktopGeometry.width(), 4191 mDesktopGeometry.height())); 4192 } 176 /* Enable/Disable guest auto-resizing depending on advanced graphics availablability: */ 177 sltToggleGuestAutoresize(bIsGraphicsSupported && m_bIsGuestAutoresizeEnabled); 4193 178 } 4194 4195 /**4196 * Sets the minimum size restriction depending on the auto-resize feature4197 * state and the current rendering mode.4198 *4199 * Currently, the restriction is set only in SDL mode and only when the4200 * auto-resize feature is inactive. We need to do that because we cannot4201 * correctly draw in a scrolled window in SDL mode.4202 *4203 * In all other modes, or when auto-resize is in force, this function does4204 * nothing.4205 */4206 void VBoxConsoleView::maybeRestrictMinimumSize()4207 {4208 if (mode == VBoxDefs::SDLMode)4209 {4210 if (!mGuestSupportsGraphics || !mAutoresizeGuest)4211 setMinimumSize (sizeHint());4212 else4213 setMinimumSize (0, 0);4214 }4215 }4216 4217 QRect VBoxConsoleView::availableGeometry() const4218 {4219 return mMainWnd->isWindowFullScreen() ?4220 QApplication::desktop()->screenGeometry(this) :4221 QApplication::desktop()->availableGeometry(this);4222 }4223 4224 int VBoxConsoleView::contentsWidth() const4225 {4226 return mFrameBuf->width();4227 }4228 4229 int VBoxConsoleView::contentsHeight() const4230 {4231 return mFrameBuf->height();4232 }4233 4234 void VBoxConsoleView::updateSliders()4235 {4236 QSize p = viewport()->size();4237 QSize m = maximumViewportSize();4238 4239 QSize v = QSize (mFrameBuf->width(), mFrameBuf->height());4240 /* no scroll bars needed */4241 if (m.expandedTo(v) == m)4242 p = m;4243 4244 horizontalScrollBar()->setRange(0, v.width() - p.width());4245 verticalScrollBar()->setRange(0, v.height() - p.height());4246 horizontalScrollBar()->setPageStep(p.width());4247 verticalScrollBar()->setPageStep(p.height());4248 }4249 4250 void VBoxConsoleView::requestToResize (const QSize &aSize)4251 {4252 mIgnoreFrameBufferResize = true;4253 mNormalSize = aSize;4254 }4255 4256 #if defined(Q_WS_MAC)4257 4258 void VBoxConsoleView::updateDockIcon()4259 {4260 if (mDockIconEnabled)4261 {4262 if (!mPausedShot.isNull())4263 {4264 CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot);4265 /* Use the pause image as background */4266 mDockIconPreview->updateDockPreview (pauseImg);4267 CGImageRelease (pauseImg);4268 }4269 else4270 {4271 # if defined (VBOX_GUI_USE_QUARTZ2D)4272 if (mode == VBoxDefs::Quartz2DMode)4273 {4274 /* If the render mode is Quartz2D we could use the CGImageRef4275 * of the framebuffer for the dock icon creation. This saves4276 * some conversion time. */4277 mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef());4278 }4279 else4280 # endif4281 /* In image mode we have to create the image ref out of the4282 * framebuffer */4283 mDockIconPreview->updateDockPreview (mFrameBuf);4284 }4285 }4286 }4287 4288 void VBoxConsoleView::updateDockOverlay()4289 {4290 /* Only to an update to the realtime preview if this is enabled by the user4291 * & we are in an state where the framebuffer is likely valid. Otherwise to4292 * the overlay stuff only. */4293 if (mDockIconEnabled &&4294 (mLastState == KMachineState_Running ||4295 mLastState == KMachineState_Paused ||4296 mLastState == KMachineState_Teleporting ||4297 mLastState == KMachineState_LiveSnapshotting ||4298 mLastState == KMachineState_Restoring ||4299 mLastState == KMachineState_TeleportingPausedVM ||4300 mLastState == KMachineState_TeleportingIn ||4301 mLastState == KMachineState_Saving))4302 updateDockIcon();4303 else4304 mDockIconPreview->updateDockOverlay();4305 }4306 4307 /**4308 * Wrapper for SetMouseCoalescingEnabled().4309 *4310 * Called by eventFilter() and darwinGrabKeyboardEvents().4311 *4312 * @param aOn Switch it on (true) or off (false).4313 */4314 void VBoxConsoleView::setMouseCoalescingEnabled (bool aOn)4315 {4316 /* Enable mouse event compression if we leave the VM view. This4317 is necessary for having smooth resizing of the VM/other4318 windows.4319 Disable mouse event compression if we enter the VM view. So4320 all mouse events are registered in the VM. Only do this if4321 the keyboard/mouse is grabbed (this is when we have a valid4322 event handler). */4323 if (aOn || mKeyboardGrabbed)4324 ::darwinSetMouseCoalescingEnabled (aOn);4325 }4326 4327 #endif /* Q_WS_MAC */4328 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleViewclass declaration4 * UIMachineViewNormal class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2007Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef ___ VBoxConsoleView_h___24 #define ___ VBoxConsoleView_h___23 #ifndef ___UIMachineViewNormal_h___ 24 #define ___UIMachineViewNormal_h___ 25 25 26 #include "COMDefs.h" 26 /* Local includes */ 27 #include "UIMachineView.h" 27 28 28 #include "VBoxDefs.h" 29 #include "VBoxGlobalSettings.h" 30 31 /* Qt includes */ 32 #include <QAbstractScrollArea> 33 #include <QScrollBar> 34 35 #if defined (Q_WS_PM) 36 #include "src/os2/VBoxHlp.h" 37 #define UM_PREACCEL_CHAR WM_USER 38 #endif 39 40 #if defined (Q_WS_MAC) 41 # include <ApplicationServices/ApplicationServices.h> 42 # ifndef QT_MAC_USE_COCOA 43 # include <Carbon/Carbon.h> 44 # endif /* !QT_MAC_USE_COCOA */ 45 #endif 46 47 class VBoxConsoleWnd; 48 class MousePointerChangeEvent; 49 class VBoxFrameBuffer; 50 class VBoxDockIconPreview; 51 52 class QPainter; 53 class QLabel; 54 class QMenuData; 55 56 class VBoxConsoleView : public QAbstractScrollArea 29 class UIMachineViewNormal : public UIMachineView 57 30 { 58 Q_OBJECT 59 60 public: 61 62 enum { 63 MouseCaptured = 0x01, 64 MouseAbsolute = 0x02, 65 MouseAbsoluteDisabled = 0x04, 66 MouseNeedsHostCursor = 0x08, 67 KeyboardCaptured = 0x01, 68 HostKeyPressed = 0x02, 69 }; 70 71 VBoxConsoleView (VBoxConsoleWnd *mainWnd, 72 const CConsole &console, 73 VBoxDefs::RenderMode rm, 74 #ifdef VBOX_WITH_VIDEOHWACCEL 75 bool accelerate2DVideo, 76 #endif 77 QWidget *parent = 0); 78 ~VBoxConsoleView(); 79 80 QSize sizeHint() const; 81 82 void attach(); 83 void detach(); 84 void refresh() { doRefresh(); } 85 void normalizeGeometry (bool adjustPosition = false); 86 87 CConsole &console() { return mConsole; } 88 89 bool pause (bool on); 90 bool isPaused() 91 { 92 return mLastState == KMachineState_Paused 93 || mLastState == KMachineState_TeleportingPausedVM; 94 } 95 const QPixmap& pauseShot() const { return mPausedShot; } 96 97 void setMouseIntegrationEnabled (bool enabled); 98 99 bool isMouseAbsolute() const { return mMouseAbsolute; } 100 101 bool shouldHideHostPointer() const 102 { return mMouseCaptured || (mMouseAbsolute && mHideHostPointer); } 103 104 void setAutoresizeGuest (bool on); 105 106 void onFullscreenChange (bool on); 107 108 void onViewOpened(); 109 110 void fixModifierState (LONG *codes, uint *count); 111 112 void toggleFSMode (const QSize &aSize = QSize()); 113 114 void setIgnoreMainwndResize (bool aYes) { mIgnoreMainwndResize = aYes; } 115 void setIgnoreGuestResize (bool aYes) { mIgnoreGuestResize = aYes; } 116 117 QRect desktopGeometry(); 118 119 QRegion lastVisibleRegion() const; 120 121 bool isAutoresizeGuestActive(); 122 123 /* todo: This are some support functions for the qt4 port. Maybe we get rid 124 * of them some day. */ 125 int contentsX() const { return horizontalScrollBar()->value(); } 126 int contentsY() const { return verticalScrollBar()->value(); } 127 int contentsWidth() const; 128 int contentsHeight() const; 129 int visibleWidth() const { return horizontalScrollBar()->pageStep(); } 130 int visibleHeight() const { return verticalScrollBar()->pageStep(); } 131 void scrollBy (int dx, int dy) 132 { 133 horizontalScrollBar()->setValue (horizontalScrollBar()->value() + dx); 134 verticalScrollBar()->setValue (verticalScrollBar()->value() + dy); 135 } 136 QPoint viewportToContents ( const QPoint & vp ) const 137 { 138 return QPoint (vp.x() + contentsX(), 139 vp.y() + contentsY()); 140 } 141 void updateSliders(); 142 143 void requestToResize (const QSize &aSize); 144 145 #ifdef VBOX_WITH_VIDEOHWACCEL 146 void scrollContentsBy (int dx, int dy); 147 #endif 148 149 #if defined(Q_WS_MAC) 150 void updateDockIcon(); 151 void updateDockOverlay(); 152 void setDockIconEnabled (bool aOn) { mDockIconEnabled = aOn; }; 153 void setMouseCoalescingEnabled (bool aOn); 154 #endif 155 156 signals: 157 158 void keyboardStateChanged (int state); 159 void mouseStateChanged (int state); 160 void machineStateChanged (KMachineState state); 161 void additionsStateChanged (const QString &, bool, bool, bool); 162 void mediaDriveChanged (VBoxDefs::MediumType aType); 163 void networkStateChange(); 164 void usbStateChange(); 165 void sharedFoldersChanged(); 166 void resizeHintDone(); 31 Q_OBJECT; 167 32 168 33 protected: 169 34 170 // events 171 bool event (QEvent *e); 172 bool eventFilter (QObject *watched, QEvent *e); 35 UIMachineViewNormal( UIMachineWindow *pMachineWindow 36 , VBoxDefs::RenderMode renderMode 37 #ifdef VBOX_WITH_VIDEOHWACCEL 38 , bool bAccelerate2DVideo 39 #endif 40 ); 173 41 174 #if defined(Q_WS_WIN32) 175 bool winLowKeyboardEvent (UINT msg, const KBDLLHOOKSTRUCT &event); 176 bool winEvent (MSG *aMsg, long *aResult); 177 #elif defined(Q_WS_PM) 178 bool pmEvent (QMSG *aMsg); 179 #elif defined(Q_WS_X11) 180 bool x11Event (XEvent *event); 181 #elif defined(Q_WS_MAC) 182 bool darwinKeyboardEvent (const void *pvCocoaEvent, EventRef inEvent); 183 void darwinGrabKeyboardEvents (bool fGrab); 184 #endif 42 void normalizeGeometry(bool bAdjustPosition = false); 185 43 186 private: 187 188 /** Flags for keyEvent(). */ 189 enum { 190 KeyExtended = 0x01, 191 KeyPressed = 0x02, 192 KeyPause = 0x04, 193 KeyPrint = 0x08, 194 }; 195 196 void focusEvent (bool aHasFocus, bool aReleaseHostKey = true); 197 bool keyEvent (int aKey, uint8_t aScan, int aFlags, 198 wchar_t *aUniKey = NULL); 199 bool mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos, 200 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 201 int aWheelDelta, Qt::Orientation aWheelDir); 202 203 void emitKeyboardStateChanged() 204 { 205 emit keyboardStateChanged ( 206 (mKbdCaptured ? KeyboardCaptured : 0) | 207 (mIsHostkeyPressed ? HostKeyPressed : 0)); 208 } 209 210 void emitMouseStateChanged() { 211 emit mouseStateChanged ((mMouseCaptured ? MouseCaptured : 0) | 212 (mMouseAbsolute ? MouseAbsolute : 0) | 213 (!mMouseIntegration ? MouseAbsoluteDisabled : 0)); 214 } 215 216 // IConsoleCallback event handlers 217 void onStateChange (KMachineState state); 218 219 void doRefresh(); 220 221 void resizeEvent (QResizeEvent *); 222 void moveEvent (QMoveEvent *); 223 void paintEvent (QPaintEvent *); 224 225 void captureKbd (bool aCapture, bool aEmitSignal = true); 226 void captureMouse (bool aCapture, bool aEmitSignal = true); 227 228 bool processHotKey (const QKeySequence &key, const QList<QAction*>& data); 229 void updateModifiers (bool fNumLock, bool fCapsLock, bool fScrollLock); 230 231 void releaseAllPressedKeys (bool aReleaseHostKey = true); 232 void saveKeyStates(); 233 void sendChangedKeyStates(); 234 void updateMouseClipping(); 235 236 void setPointerShape (MousePointerChangeEvent *me); 237 238 bool isRunning() 239 { 240 return mLastState == KMachineState_Running 241 || mLastState == KMachineState_Teleporting 242 || mLastState == KMachineState_LiveSnapshotting; 243 } 244 245 static void dimImage (QImage &img); 44 void maybeRestrictMinimumSize(); 246 45 247 46 private slots: 248 47 249 void doResizeHint (const QSize &aSize = QSize()); 250 void doResizeDesktop (int); 48 void doResizeHint(const QSize &aSize = QSize()); 251 49 50 void doResizeDesktop(int); 51 52 void sltToggleGuestAutoresize(bool bOn); 53 54 void sltAdditionsStateChanged(const QString &strVersion, bool bIsActive, 55 bool bIsSeamlessSupported, bool bIsGraphicsSupported); 252 56 private: 253 57 254 enum DesktopGeo 255 { 256 DesktopGeo_Invalid = 0, DesktopGeo_Fixed, 257 DesktopGeo_Automatic, DesktopGeo_Any 258 }; 58 bool m_bIsGuestAutoresizeEnabled : 1; 259 59 260 void setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight); 261 void storeConsoleSize (int aWidth, int aHeight); 262 void calculateDesktopGeometry(); 263 void maybeRestrictMinimumSize(); 264 QRect availableGeometry() const; 265 266 VBoxConsoleWnd *mMainWnd; 267 268 CConsole mConsole; 269 270 const VBoxGlobalSettings &gs; 271 272 KMachineState mLastState; 273 274 bool mAttached : 1; 275 bool mKbdCaptured : 1; 276 bool mMouseCaptured : 1; 277 bool mMouseAbsolute : 1; 278 bool mMouseIntegration : 1; 279 QPoint mLastPos; 280 QPoint mCapturedPos; 281 int m_iLastMouseWheelDelta; 282 283 bool mDisableAutoCapture : 1; 284 285 enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 }; 286 uint8_t mPressedKeys [128]; 287 uint8_t mPressedKeysCopy [128]; 288 289 bool mIsHostkeyPressed : 1; 290 bool mIsHostkeyAlone : 1; 291 292 /** mKbdCaptured value during the the last host key press or release */ 293 bool hostkey_in_capture : 1; 294 295 bool mIgnoreMainwndResize : 1; 296 bool mAutoresizeGuest : 1; 297 bool mIgnoreFrameBufferResize : 1; 298 bool mIgnoreGuestResize : 1; 299 300 /** 301 * This flag indicates whether the last console resize should trigger 302 * a size hint to the guest. This is important particularly when 303 * enabling the autoresize feature to know whether to send a hint. 304 */ 305 bool mDoResize : 1; 306 307 bool mGuestSupportsGraphics : 1; 308 309 bool mNumLock : 1; 310 bool mScrollLock : 1; 311 bool mCapsLock : 1; 312 long muNumLockAdaptionCnt; 313 long muCapsLockAdaptionCnt; 314 315 316 VBoxDefs::RenderMode mode; 317 #ifdef VBOX_WITH_VIDEOHWACCEL 318 bool mAccelerate2DVideo; 319 #endif 320 321 QRegion mLastVisibleRegion; 322 QSize mNormalSize; 323 324 #if defined(Q_WS_WIN) 325 HCURSOR mAlphaCursor; 326 #endif 327 328 #if defined(Q_WS_MAC) 329 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA) 330 /** Event handler reference. NULL if the handler isn't installed. */ 331 EventHandlerRef mDarwinEventHandlerRef; 332 # endif 333 /** The current modifier key mask. Used to figure out which modifier 334 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 335 UInt32 mDarwinKeyModifiers; 336 bool mKeyboardGrabbed; 337 #endif 338 339 VBoxFrameBuffer *mFrameBuf; 340 CConsoleCallback mCallback; 341 342 friend class VBoxConsoleCallback; 343 344 #if defined (Q_WS_WIN32) 345 static LRESULT CALLBACK lowLevelKeyboardProc (int nCode, 346 WPARAM wParam, LPARAM lParam); 347 #elif defined (Q_WS_MAC) 348 # if defined (QT_MAC_USE_COCOA) 349 static bool darwinEventHandlerProc (const void *pvCocoaEvent, const 350 void *pvCarbonEvent, void *pvUser); 351 # elif !defined (VBOX_WITH_HACKED_QT) 352 static pascal OSStatus darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef, 353 EventRef inEvent, void *inUserData); 354 # else /* VBOX_WITH_HACKED_QT */ 355 static bool macEventFilter (EventRef inEvent, void *inUserData); 356 # endif /* VBOX_WITH_HACKED_QT */ 357 #endif 358 359 QPixmap mPausedShot; 360 #if defined(Q_WS_MAC) 361 # if !defined (QT_MAC_USE_COCOA) 362 EventHandlerRef mDarwinWindowOverlayHandlerRef; 363 # endif 364 VBoxDockIconPreview *mDockIconPreview; 365 bool mDockIconEnabled; 366 #endif 367 DesktopGeo mDesktopGeo; 368 QRect mDesktopGeometry; 369 QRect mStoredConsoleSize; 370 bool mPassCAD; 371 bool mHideHostPointer; 372 QCursor mLastCursor; 60 friend class UIMachineView; 373 61 }; 374 62 375 #endif // !___VBoxConsoleView_h___ 376 63 #endif // !___UIMachineViewNormal_h___ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass implementation4 * UIMachineWindowNormal class implementation 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010 Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 23 23 /* Global includes */ 24 #ifdef VBOX_WITH_PRECOMPILED_HEADERS25 # include "precomp.h"26 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */27 #include <QActionGroup>28 24 #include <QDesktopWidget> 29 #include <QDir>30 #include <QFileInfo>31 25 #include <QMenuBar> 32 #include <QProgressBar>33 26 #include <QTimer> 34 27 #include <QContextMenuEvent> 28 29 /* Local includes */ 30 #include "VBoxGlobal.h" 31 32 #include "VBoxVMInformationDlg.h" 33 34 #include "UIActionsPool.h" 35 #include "UIIndicatorsPool.h" 36 #include "UIMachineLogic.h" 37 #include "UIMachineView.h" 38 #include "UIMachineWindowNormal.h" 39 40 #include "QIStatusBar.h" 41 #include "QIStateIndicator.h" 42 #include "QIHotKeyEdit.h" 43 44 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic) 45 : QIWithRetranslateUI<QIMainDialog>(0) 46 , UIMachineWindow(pMachineLogic) 47 , m_pIndicatorsPool(new UIIndicatorsPool(this)) 48 , m_pIdleTimer(0) 49 { 50 /* "This" is machine window: */ 51 m_pMachineWindow = this; 52 53 /* Prepare menu: */ 54 prepareMenu(); 55 56 /* Prepare status bar: */ 57 prepareStatusBar(); 58 59 /* Prepare connections: */ 60 prepareConnections(); 61 62 /* Prepare normal machine view: */ 63 prepareMachineView(); 64 65 /* Load normal window settings: */ 66 loadWindowSettings(); 67 68 /* Retranslate normal window finally: */ 69 retranslateUi(); 70 } 71 72 UIMachineWindowNormal::~UIMachineWindowNormal() 73 { 74 /* Save normal window settings: */ 75 saveWindowSettings(); 76 77 /* Cleanup status-bar: */ 78 cleanupStatusBar(); 79 } 80 81 void UIMachineWindowNormal::sltTryClose() 82 { 83 // TODO: Could be moved to parent class? 84 85 /* First close any open modal & popup widgets. 86 * Use a single shot with timeout 0 to allow the widgets to cleany close and test then again. 87 * If all open widgets are closed destroy ourself: */ 88 QWidget *widget = QApplication::activeModalWidget() ? 89 QApplication::activeModalWidget() : 90 QApplication::activePopupWidget() ? 91 QApplication::activePopupWidget() : 0; 92 if (widget) 93 { 94 widget->close(); 95 QTimer::singleShot(0, this, SLOT(sltTryClose())); 96 } 97 else 98 close(); 99 } 100 101 void UIMachineWindowNormal::sltPrepareMenuMachine() 102 { 103 QMenu *menu = qobject_cast<QMenu*>(sender()); 104 AssertMsg(menu == machineLogic()->actionsPool()->action(UIActionIndex_Menu_Machine)->menu(), 105 ("This slot should only be called on 'Machine' menu hovering!\n")); 106 107 menu->clear(); 108 109 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Fullscreen)); 110 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Seamless)); 111 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)); 112 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_AdjustWindow)); 113 menu->addSeparator(); 114 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)); 115 menu->addSeparator(); 116 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_TypeCAD)); 35 117 #ifdef Q_WS_X11 36 # include <QX11Info> 118 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_TypeCABS)); 37 119 #endif 38 #ifdef Q_WS_MAC 39 # include <QPainter> 40 #endif 41 42 /* Local includes */ 43 #include "QIFileDialog.h" 44 #include "QIHotKeyEdit.h" 45 #include "QIHttp.h" 46 #include "QIStateIndicator.h" 47 #include "QIStatusBar.h" 48 #include "QIWidgetValidator.h" 49 #include "QIHotKeyEdit.h" 50 #include "VBoxConsoleWnd.h" 51 #include "VBoxConsoleView.h" 52 #include "VBoxCloseVMDlg.h" 53 #include "VBoxDownloaderWgt.h" 54 #include "VBoxGlobal.h" 55 #include "VBoxMediaManagerDlg.h" 56 #include "VBoxMiniToolBar.h" 57 #include "VBoxProblemReporter.h" 58 #include "VBoxTakeSnapshotDlg.h" 59 #include "UIFirstRunWzd.h" 60 #include "VBoxVMSettingsNetwork.h" 61 #include "VBoxVMSettingsSF.h" 62 #include "VBoxVMInformationDlg.h" 63 64 #ifdef Q_WS_X11 65 # include <X11/Xlib.h> 66 # include <XKeyboard.h> 67 #endif 68 #ifdef Q_WS_MAC 69 # include "VBoxUtils.h" 70 # include "VBoxIChatTheaterWrapper.h" 71 # include <ApplicationServices/ApplicationServices.h> 72 #endif 120 menu->addSeparator(); 121 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_TakeSnapshot)); 122 menu->addSeparator(); 123 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_InformationDialog)); 124 menu->addSeparator(); 125 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Reset)); 126 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Pause)); 127 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Shutdown)); 128 #ifndef Q_WS_MAC 129 menu->addSeparator(); 130 #endif /* Q_WS_MAC */ 131 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Close)); 132 } 133 134 void UIMachineWindowNormal::sltPrepareMenuDevices() 135 { 136 QMenu *menu = qobject_cast<QMenu*>(sender()); 137 AssertMsg(menu == machineLogic()->actionsPool()->action(UIActionIndex_Menu_Devices)->menu(), 138 ("This slot should only be called on 'Devices' menu hovering!\n")); 139 140 menu->clear(); 141 142 /* Devices submenu */ 143 menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu()); 144 menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu()); 145 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)); 146 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog)); 147 menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()); 148 menu->addSeparator(); 149 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_VRDP)); 150 menu->addSeparator(); 151 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_InstallGuestTools)); 152 } 153 73 154 #ifdef VBOX_WITH_DEBUGGER_GUI 74 # include <VBox/err.h> 75 # include <iprt/ldr.h> 76 #endif 77 78 #include <VBox/VMMDev.h> /** @todo @bugref{4084} */ 79 #include <iprt/buildconfig.h> 80 #include <iprt/param.h> 81 #include <iprt/path.h> 82 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 83 84 /* Global forwards */ 85 extern void qt_set_sequence_auto_mnemonic (bool on); 86 87 /** class StatusTipEvent 88 * 89 * The StatusTipEvent class is an auxiliary QEvent class 90 * for carrying statusTip text of non-QAction menu item's. 91 * This event is posted then the menu item is highlighted but 92 * processed later in VBoxConsoleWnd::event() handler to 93 * avoid statusBar messaging collisions. 94 */ 95 class StatusTipEvent : public QEvent 96 { 97 public: 98 enum { Type = QEvent::User + 10 }; 99 StatusTipEvent (const QString &aTip) 100 : QEvent ((QEvent::Type) Type), mTip (aTip) {} 101 102 QString mTip; 103 }; 104 105 class VBoxAdditionsDownloader : public VBoxDownloaderWgt 106 { 107 Q_OBJECT; 108 109 public: 110 111 VBoxAdditionsDownloader (const QString &aSource, const QString &aTarget, QAction *aAction) 112 : VBoxDownloaderWgt (aSource, aTarget) 113 , mAction (aAction) 114 { 115 mAction->setEnabled (false); 116 retranslateUi(); 117 } 118 119 void start() 120 { 121 acknowledgeStart(); 122 } 123 124 protected: 125 126 void retranslateUi() 127 { 128 mCancelButton->setText (tr ("Cancel")); 129 mProgressBar->setToolTip (tr ("Downloading the VirtualBox Guest Additions " 130 "CD image from <nobr><b>%1</b>...</nobr>") 131 .arg (mSource.toString())); 132 mCancelButton->setToolTip (tr ("Cancel the VirtualBox Guest " 133 "Additions CD image download")); 134 } 135 136 private slots: 137 138 void downloadFinished (bool aError) 139 { 140 if (aError) 141 VBoxDownloaderWgt::downloadFinished (aError); 142 else 143 { 144 QByteArray receivedData (mHttp->readAll()); 145 /* Serialize the incoming buffer into the .iso image. */ 146 while (true) 155 void UIMachineWindowNormal::sltPrepareMenuDebug() 156 { 157 QMenu *menu = qobject_cast<QMenu*>(sender()); 158 AssertMsg(menu == machineLogic()->actionsPool()->action(UIActionIndex_Menu_Debug)->menu(), 159 ("This slot should only be called on 'Debug' menu hovering!\n")); 160 161 menu->clear(); 162 163 /* Debug submenu */ 164 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Statistics)); 165 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_CommandLine)); 166 menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Logging)); 167 } 168 #endif /* VBOX_WITH_DEBUGGER_GUI */ 169 170 void UIMachineWindowNormal::sltUpdateIndicators() 171 { 172 CConsole console = machineLogic()->session().GetConsole(); 173 QIStateIndicator *pStateIndicator = 0; 174 175 pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_HardDisks); 176 if (pStateIndicator->state() != KDeviceActivity_Null) 177 { 178 int state = console.GetDeviceActivity(KDeviceType_HardDisk); 179 if (pStateIndicator->state() != state) 180 pStateIndicator->setState(state); 181 } 182 pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks); 183 if (pStateIndicator->state() != KDeviceActivity_Null) 184 { 185 int state = console.GetDeviceActivity(KDeviceType_DVD); 186 if (pStateIndicator->state() != state) 187 pStateIndicator->setState(state); 188 } 189 pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters); 190 if (pStateIndicator->state() != KDeviceActivity_Null) 191 { 192 int state = console.GetDeviceActivity(KDeviceType_Network); 193 if (pStateIndicator->state() != state) 194 pStateIndicator->setState(state); 195 } 196 pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices); 197 if (pStateIndicator->state() != KDeviceActivity_Null) 198 { 199 int state = console.GetDeviceActivity(KDeviceType_USB); 200 if (pStateIndicator->state() != state) 201 pStateIndicator->setState(state); 202 } 203 pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders); 204 if (pStateIndicator->state() != KDeviceActivity_Null) 205 { 206 int state = console.GetDeviceActivity(KDeviceType_SharedFolder); 207 if (pStateIndicator->state() != state) 208 pStateIndicator->setState(state); 209 } 210 } 211 212 void UIMachineWindowNormal::sltShowIndicatorsContextMenu(QIStateIndicator *pIndicator, QContextMenuEvent *pEvent) 213 { 214 if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks)) 215 { 216 if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu()->isEnabled()) 217 machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu()->exec(pEvent->globalPos()); 218 } 219 else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)) 220 { 221 if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->menu()->isEnabled()) 222 machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->menu()->exec(pEvent->globalPos()); 223 } 224 else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_USBDevices)) 225 { 226 if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->isEnabled()) 227 machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->exec(pEvent->globalPos()); 228 } 229 else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders)) 230 { 231 if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->isEnabled()) 232 machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->exec(pEvent->globalPos()); 233 } 234 else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_Mouse)) 235 { 236 if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->menu()->isEnabled()) 237 machineLogic()->actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->menu()->exec(pEvent->globalPos()); 238 } 239 } 240 241 void UIMachineWindowNormal::sltProcessGlobalSettingChange(const char * /* aPublicName */, const char * /* aName */) 242 { 243 m_pNameHostkey->setText(QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey())); 244 } 245 246 void UIMachineWindowNormal::sltUpdateMediaDriveState(VBoxDefs::MediumType type) 247 { 248 Assert(type == VBoxDefs::MediumType_DVD || type == VBoxDefs::MediumType_Floppy); 249 updateAppearanceOf(type == VBoxDefs::MediumType_DVD ? UIVisualElement_CDStuff : 250 type == VBoxDefs::MediumType_Floppy ? UIVisualElement_FDStuff : 251 UIVisualElement_AllStuff); 252 } 253 254 void UIMachineWindowNormal::sltUpdateNetworkAdaptersState() 255 { 256 updateAppearanceOf(UIVisualElement_NetworkStuff); 257 } 258 259 void UIMachineWindowNormal::sltUpdateUsbState() 260 { 261 updateAppearanceOf(UIVisualElement_USBStuff); 262 } 263 264 void UIMachineWindowNormal::sltUpdateSharedFoldersState() 265 { 266 updateAppearanceOf(UIVisualElement_SharedFolderStuff); 267 } 268 269 void UIMachineWindowNormal::sltUpdateMouseState(int iState) 270 { 271 if ((iState & UIMouseStateType_MouseAbsoluteDisabled) && 272 (iState & UIMouseStateType_MouseAbsolute) && 273 !(iState & UIMouseStateType_MouseCaptured)) 274 { 275 indicatorsPool()->indicator(UIIndicatorIndex_Mouse)->setState(4); 276 } 277 else 278 { 279 indicatorsPool()->indicator(UIIndicatorIndex_Mouse)->setState( 280 iState & (UIMouseStateType_MouseAbsolute | UIMouseStateType_MouseCaptured)); 281 } 282 } 283 284 void UIMachineWindowNormal::retranslateUi() 285 { 286 /* Translate parent class: */ 287 retranslateWindow(); 288 } 289 290 void UIMachineWindowNormal::updateAppearanceOf(int iElement) 291 { 292 /* Update parent-class window: */ 293 UIMachineWindow::updateAppearanceOf(iElement); 294 295 // TODO: Move most of this update code into indicators-pool! 296 297 /* Update that machine window: */ 298 CMachine machine = machineLogic()->session().GetMachine(); 299 CConsole console = machineLogic()->session().GetConsole(); 300 bool bIsStrictRunningOrPaused = machineLogic()->machineState() == KMachineState_Running || 301 machineLogic()->machineState() == KMachineState_Paused; 302 303 if (iElement & UIVisualElement_HDStuff) 304 { 305 QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity " 306 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 307 308 QString strFullData; 309 bool bAttachmentsPresent = false; 310 311 CStorageControllerVector controllers = machine.GetStorageControllers(); 312 foreach (const CStorageController &controller, controllers) 313 { 314 QString strAttData; 315 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName()); 316 foreach (const CMediumAttachment &attachment, attachments) 147 317 { 148 QFile file (mTarget); 149 if (file.open (QIODevice::WriteOnly)) 318 if (attachment.GetType() != KDeviceType_HardDisk) 319 continue; 320 strAttData += QString("<br> <nobr>%1: %2</nobr>") 321 .arg(vboxGlobal().toString(StorageSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 322 .arg(VBoxMedium(attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 323 bAttachmentsPresent = true; 324 } 325 if (!strAttData.isNull()) 326 strFullData += QString("<br><nobr><b>%1</b></nobr>").arg(controller.GetName()) + strAttData; 327 } 328 329 if (!bAttachmentsPresent) 330 strFullData += tr("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 331 332 indicatorsPool()->indicator(UIIndicatorIndex_HardDisks)->setToolTip(strToolTip.arg(strFullData)); 333 indicatorsPool()->indicator(UIIndicatorIndex_HardDisks)->setState(bAttachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 334 } 335 if (iElement & UIVisualElement_CDStuff) 336 { 337 QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity " 338 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 339 340 QString strFullData; 341 bool bAttachmentsPresent = false; 342 343 CStorageControllerVector controllers = machine.GetStorageControllers(); 344 foreach (const CStorageController &controller, controllers) 345 { 346 QString strAttData; 347 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName()); 348 foreach (const CMediumAttachment &attachment, attachments) 349 { 350 if (attachment.GetType() != KDeviceType_DVD) 351 continue; 352 VBoxMedium vboxMedium(attachment.GetMedium(), VBoxDefs::MediumType_DVD); 353 strAttData += QString("<br> <nobr>%1: %2</nobr>") 354 .arg(vboxGlobal().toString(StorageSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 355 .arg(vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 356 if (!vboxMedium.isNull()) 357 bAttachmentsPresent = true; 358 } 359 if (!strAttData.isNull()) 360 strFullData += QString("<br><nobr><b>%1</b></nobr>").arg(controller.GetName()) + strAttData; 361 } 362 363 if (strFullData.isNull()) 364 strFullData = tr("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 365 366 indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks)->setToolTip(strToolTip.arg(strFullData)); 367 indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks)->setState(bAttachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 368 } 369 if (iElement & UIVisualElement_NetworkStuff) 370 { 371 ulong uMaxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 372 ulong uCount = 0; 373 for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot) 374 if (machine.GetNetworkAdapter(uSlot).GetEnabled()) 375 ++ uCount; 376 indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setState(uCount > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 377 378 machineLogic()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)->setEnabled(bIsStrictRunningOrPaused && uCount > 0); 379 machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->setEnabled(bIsStrictRunningOrPaused && uCount > 0); 380 381 QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity of the " 382 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 383 QString strFullData; 384 385 for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot) 386 { 387 CNetworkAdapter adapter = machine.GetNetworkAdapter(uSlot); 388 if (adapter.GetEnabled()) 389 strFullData += tr("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 390 .arg(uSlot + 1) 391 .arg(vboxGlobal().toString(adapter.GetAttachmentType())) 392 .arg(adapter.GetCableConnected() ? 393 tr("connected", "Network adapters tooltip") : 394 tr("disconnected", "Network adapters tooltip")); 395 } 396 397 if (strFullData.isNull()) 398 strFullData = tr("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 399 400 indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setToolTip(strToolTip.arg(strFullData)); 401 } 402 if (iElement & UIVisualElement_USBStuff) 403 { 404 if (!indicatorsPool()->indicator(UIIndicatorIndex_USBDevices)->isHidden()) 405 { 406 QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity of " 407 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 408 QString strFullData; 409 410 CUSBController usbctl = machine.GetUSBController(); 411 if (!usbctl.isNull() && usbctl.GetEnabled()) 412 { 413 machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(bIsStrictRunningOrPaused); 414 415 CUSBDeviceVector devsvec = console.GetUSBDevices(); 416 for (int i = 0; i < devsvec.size(); ++ i) 150 417 { 151 file.write (receivedData); 152 file.close(); 153 if (vboxProblem().confirmMountAdditions (mSource.toString(), 154 QDir::toNativeSeparators (mTarget))) 155 vboxGlobal().consoleWnd().installGuestAdditionsFrom (mTarget); 156 QTimer::singleShot (0, this, SLOT (suicide())); 157 break; 418 CUSBDevice usb = devsvec[i]; 419 strFullData += QString("<br><b><nobr>%1</nobr></b>").arg(vboxGlobal().details(usb)); 158 420 } 159 else 160 { 161 vboxProblem().message (window(), VBoxProblemReporter::Error, 162 tr ("<p>Failed to save the downloaded file as " 163 "<nobr><b>%1</b>.</nobr></p>") 164 .arg (QDir::toNativeSeparators (mTarget))); 165 } 166 167 QString target = QIFileDialog::getExistingDirectory ( 168 QFileInfo (mTarget).absolutePath(), this, 169 tr ("Select folder to save Guest Additions image to"), true); 170 if (target.isNull()) 171 QTimer::singleShot (0, this, SLOT (suicide())); 172 else 173 mTarget = QDir (target).absoluteFilePath (QFileInfo (mTarget).fileName()); 421 if (strFullData.isNull()) 422 strFullData = tr("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 174 423 } 175 }176 }177 178 void suicide()179 {180 QStatusBar *sb = qobject_cast <QStatusBar*> (parent()); 181 Assert (sb);182 sb->removeWidget (this);183 mAction->setEnabled (true);184 VBoxDownloaderWgt::suicide();185 }186 187 private: 188 189 bool confirmDownload()190 {191 return vboxProblem().confirmDownloadAdditions (mSource.toString(),192 mHttp->lastResponse().contentLength());193 } 194 195 void warnAboutError (const QString &aError)196 {197 return vboxProblem().cannotDownloadGuestAdditions (mSource.toString(), aError);198 } 199 200 QAction *mAction;201 }; 202 203 struct MountTarget 204 { 205 MountTarget() : name (QString ("")), port (0), device (0), id (QString()), type (VBoxDefs::MediumType_Invalid) {}206 MountTarget (const QString &aName, LONG aPort, LONG aDevice) 207 : name (aName), port (aPort), device (aDevice), id (QString()), type (VBoxDefs::MediumType_Invalid) {}208 MountTarget (const QString &aName, LONG aPort, LONG aDevice, const QString &aId)209 : name (aName), port (aPort), device (aDevice), id (aId), type (VBoxDefs::MediumType_Invalid) {}210 MountTarget (const QString &aName, LONG aPort, LONG aDevice, VBoxDefs::MediumType aType)211 : name (aName), port (aPort), device (aDevice), id (QString()), type (aType) {}212 QString name; 213 LONG port;214 LONG device;215 QString id; 216 VBoxDefs::MediumType type;217 }; 218 Q_DECLARE_METATYPE (MountTarget);219 220 int searchMaxSnapshotIndex (const CMachine &aMachine, const CSnapshot &aSnapshot, const QString &aNameTemplate) 221 { 222 int maxIndex = 0;223 QRegExp regExp (QString ("^") + aNameTemplate.arg ("([0-9]+)") + QString ("$"));224 if (!aSnapshot.isNull())225 {226 /* Check the current snapshot name */227 QString name = aSnapshot.GetName();228 int pos = regExp.indexIn (name);229 if (pos != -1)230 maxIndex = regExp.cap (1).toInt() > maxIndex ? regExp.cap (1).toInt() : maxIndex;231 /* Traversing all the snapshot children */232 foreach (const CSnapshot &child, aSnapshot.GetChildren()) 233 {234 int maxIndexOfChildren = searchMaxSnapshotIndex (aMachine, child, aNameTemplate);235 maxIndex = maxIndexOfChildren > maxIndex ? maxIndexOfChildren : maxIndex; 236 }237 } 238 return maxIndex;239 } 240 241 /** \class VBoxConsoleWnd 242 *243 * The VBoxConsoleWnd class is a VM console window, one of two main VBox244 * GUI windows. 245 *246 * This window appears when the user starts the virtual machine. It247 * contains the VBoxConsoleView widget that acts as a console of the248 * running virtual machine.249 */ 250 251 /** 252 * Constructs the VM console window.253 *254 * @param aSelf pointer to a variable where to store |this| right after255 * this object's constructor is called (necessary to avoid256 * recursion in VBoxGlobal::consoleWnd())257 */ 258 VBoxConsoleWnd::VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent, Qt::WindowFlags aFlags /* = Qt::Window */) 259 : QIWithRetranslateUI2 <QMainWindow> (aParent, aFlags)260 /* Machine State */261 , mMachineState (KMachineState_Null)262 /* Window Variables */ 263 , mConsoleStyle (0)264 /* Menu Items */265 , mMainMenu (0)266 , mVMMenu (0) 267 , mVMMenuMini (0) 268 , mDevicesMenu (0)269 , mDevicesCDMenu (0) 270 , mDevicesFDMenu (0)271 , mDevicesNetworkMenu (0)272 , mDevicesSFMenu (0)273 , mDevicesUSBMenu (0)274 , mVmDisMouseIntegrMenu (0)275 #if 0 /* TODO: Allow to setup status-bar! */ 276 , mDevicesVRDPMenu (0)277 , mVmAutoresizeMenu (0)278 #endif 424 else 425 { 426 machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(false); 427 strFullData = tr("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 428 } 429 430 indicatorsPool()->indicator(UIIndicatorIndex_USBDevices)->setToolTip(strToolTip.arg(strFullData)); 431 } 432 } 433 if (iElement & UIVisualElement_VRDPStuff) 434 { 435 CVRDPServer vrdpsrv = machineLogic()->session().GetMachine().GetVRDPServer(); 436 if (!vrdpsrv.isNull()) 437 { 438 /* Update menu&status icon state */ 439 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 440 machineLogic()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setChecked(isVRDPEnabled); 441 } 442 } 443 if (iElement & UIVisualElement_SharedFolderStuff) 444 { 445 QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity of " 446 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 447 448 QString strFullData; 449 QMap<QString, QString> sfs; 450 451 machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->setEnabled(true); 452 453 /* Permanent folders */ 454 CSharedFolderVector psfvec = machine.GetSharedFolders(); 455 456 for (int i = 0; i < psfvec.size(); ++ i) 457 { 458 CSharedFolder sf = psfvec[i]; 459 sfs.insert(sf.GetName(), sf.GetHostPath()); 460 } 461 462 /* Transient folders */ 463 CSharedFolderVector tsfvec = console.GetSharedFolders(); 464 465 for (int i = 0; i < tsfvec.size(); ++ i) 466 { 467 CSharedFolder sf = tsfvec[i]; 468 sfs.insert(sf.GetName(), sf.GetHostPath()); 469 } 470 471 for (QMap<QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 472 { 473 /* Select slashes depending on the OS type */ 474 if (VBoxGlobal::isDOSType(console.GetGuest().GetOSTypeId())) 475 strFullData += QString("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 476 .arg(it.key(), it.value()); 477 else 478 strFullData += QString("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 479 .arg(it.key(), it.value()); 480 } 481 482 if (sfs.count() == 0) 483 strFullData = tr("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 484 485 indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders)->setToolTip(strToolTip.arg(strFullData)); 486 } 487 if (iElement & UIVisualElement_VirtualizationStuff) 488 { 489 bool bVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 490 QString virtualization = bVirtEnabled ? 491 VBoxGlobal::tr("Enabled", "details report (VT-x/AMD-V)") : 492 VBoxGlobal::tr("Disabled", "details report (VT-x/AMD-V)"); 493 494 bool bNestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 495 QString nestedPaging = bNestEnabled ? 496 VBoxVMInformationDlg::tr("Enabled", "nested paging") : 497 VBoxVMInformationDlg::tr("Disabled", "nested paging"); 498 499 QString tip(tr("Indicates the status of the hardware virtualization " 500 "features used by this virtual machine:" 501 "<br><nobr><b>%1:</b> %2</nobr>" 502 "<br><nobr><b>%3:</b> %4</nobr>", 503 "Virtualization Stuff LED") 504 .arg(VBoxGlobal::tr("VT-x/AMD-V", "details report"), virtualization) 505 .arg(VBoxVMInformationDlg::tr("Nested Paging"), nestedPaging)); 506 507 int cpuCount = console.GetMachine().GetCPUCount(); 508 if (cpuCount > 1) 509 tip += tr("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 510 .arg(VBoxGlobal::tr("Processor(s)", "details report")).arg(cpuCount); 511 512 indicatorsPool()->indicator(UIIndicatorIndex_Virtualization)->setToolTip(tip); 513 indicatorsPool()->indicator(UIIndicatorIndex_Virtualization)->setState(bVirtEnabled); 514 } 515 } 516 517 bool UIMachineWindowNormal::event(QEvent *pEvent) 518 { 519 switch (pEvent->type()) 520 { 521 case QEvent::Resize: 522 { 523 QResizeEvent *pResizeEvent = (QResizeEvent*)pEvent; 524 525 if (!isMaximized()) 526 { 527 m_normalGeometry.setSize(pResizeEvent->size()); 279 528 #ifdef VBOX_WITH_DEBUGGER_GUI 280 , mDbgMenu (0) 281 #endif 282 , mHelpMenu (0) 283 /* Action Groups */ 284 , mRunningActions (0) 285 , mRunningOrPausedActions (0) 286 /* Machine Menu Actions */ 287 , mVmFullscreenAction (0) 288 , mVmSeamlessAction (0) 289 , mVmAutoresizeGuestAction (0) 290 , mVmAdjustWindowAction (0) 291 , mVmDisableMouseIntegrAction (0) 292 , mVmTypeCADAction (0) 293 #ifdef Q_WS_X11 294 , mVmTypeCABSAction (0) 295 #endif 296 , mVmTakeSnapshotAction (0) 297 , mVmShowInformationDlgAction (0) 298 , mVmResetAction (0) 299 , mVmPauseAction (0) 300 , mVmACPIShutdownAction (0) 301 , mVmCloseAction (0) 302 /* Device Menu Actions */ 303 , mDevicesNetworkDialogAction (0) 304 , mDevicesSFDialogAction (0) 305 , mDevicesSwitchVrdpSeparator (0) 306 , mDevicesSwitchVrdpAction (0) 307 , mDevicesInstallGuestToolsAction (0) 308 #ifdef VBOX_WITH_DEBUGGER_GUI 309 /* Debug Menu Actions */ 310 , mDbgStatisticsAction (0) 311 , mDbgCommandLineAction (0) 312 , mDbgLoggingAction (0) 313 #endif 314 /* Widgets */ 315 , mConsole (0) 316 , mMiniToolBar (0) 317 #ifdef VBOX_WITH_DEBUGGER_GUI 318 , mDbgGui (0) 319 , mDbgGuiVT (0) 320 #endif 321 /* LED Update Timer */ 322 , mIdleTimer (new QTimer (this)) 323 /* LEDs */ 324 , mHDLed (0) 325 , mCDLed (0) 326 #if 0 /* TODO: Allow to setup status-bar! */ 327 , mFDLed (0) 328 #endif 329 , mNetLed (0) 330 , mUSBLed (0) 331 , mSFLed (0) 332 , mVirtLed (0) 333 , mMouseLed (0) 334 , mHostkeyLed (0) 335 , mHostkeyLedContainer (0) 336 , mHostkeyName (0) 337 #if 0 /* TODO: Allow to setup status-bar! */ 338 , mVrdpLed (0) 339 , mAutoresizeLed (0) 340 #endif 341 , mIsOpenViewFinished (false) 342 , mIsFirstTimeStarted (false) 343 , mIsAutoSaveMedia (true) 344 , mNoAutoClose (false) 345 , mIsFullscreen (false) 346 , mIsSeamless (false) 347 , mIsSeamlessSupported (false) 348 , mIsGraphicsSupported (false) 349 , mIsWaitingModeResize (false) 350 , mWasMax (false) 351 { 352 if (aSelf) 353 *aSelf = this; 354 355 /* Cache IMedium data! */ 356 vboxGlobal().startEnumeratingMedia(); 357 358 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 359 /* The default application icon (will change to the VM-specific icon in 360 * openView()). On Win32, it's built-in to the executable. On Mac OS X the 361 * icon referenced in info.plist is used. */ 362 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 363 #endif 364 365 /* Ensure status bar is created */ 366 setStatusBar (new QIStatusBar (this)); 367 368 /* A group for all actions that are enabled only when the VM is running. 369 * Note that only actions whose enabled state depends exclusively on the 370 * execution state of the VM are added to this group. */ 371 mRunningActions = new QActionGroup (this); 372 mRunningActions->setExclusive (false); 373 374 /* A group for all actions that are enabled when the VM is running or 375 * paused. Note that only actions whose enabled state depends exclusively 376 * on the execution state of the VM are added to this group. */ 377 mRunningOrPausedActions = new QActionGroup (this); 378 mRunningOrPausedActions->setExclusive (false); 379 380 /* VM menu actions */ 381 mVmFullscreenAction = new QAction (this); 382 mVmFullscreenAction->setIcon (VBoxGlobal::iconSetOnOff ( 383 ":/fullscreen_on_16px.png", ":/fullscreen_16px.png", 384 ":/fullscreen_on_disabled_16px.png", ":/fullscreen_disabled_16px.png")); 385 mVmFullscreenAction->setCheckable (true); 386 387 mVmSeamlessAction = new QAction (this); 388 mVmSeamlessAction->setIcon (VBoxGlobal::iconSetOnOff ( 389 ":/seamless_on_16px.png", ":/seamless_16px.png", 390 ":/seamless_on_disabled_16px.png", ":/seamless_disabled_16px.png")); 391 mVmSeamlessAction->setCheckable (true); 392 393 mVmAutoresizeGuestAction = new QAction (mRunningActions); 394 mVmAutoresizeGuestAction->setIcon (VBoxGlobal::iconSetOnOff ( 395 ":/auto_resize_on_on_16px.png", ":/auto_resize_on_16px.png", 396 ":/auto_resize_on_on_disabled_16px.png", ":/auto_resize_on_disabled_16px.png")); 397 mVmAutoresizeGuestAction->setCheckable (true); 398 mVmAutoresizeGuestAction->setEnabled (false); 399 400 mVmAdjustWindowAction = new QAction (this); 401 mVmAdjustWindowAction->setIcon (VBoxGlobal::iconSet ( 402 ":/adjust_win_size_16px.png", ":/adjust_win_size_disabled_16px.png")); 403 404 mVmDisableMouseIntegrAction = new QAction (this); 405 mVmDisableMouseIntegrAction->setIcon (VBoxGlobal::iconSetOnOff ( 406 ":/mouse_can_seamless_on_16px.png", ":/mouse_can_seamless_16px.png", 407 ":/mouse_can_seamless_on_disabled_16px.png", ":/mouse_can_seamless_disabled_16px.png")); 408 mVmDisableMouseIntegrAction->setCheckable (true); 409 410 mVmTypeCADAction = new QAction (mRunningActions); 411 mVmTypeCADAction->setIcon (VBoxGlobal::iconSet ( 412 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 413 414 #if defined(Q_WS_X11) 415 mVmTypeCABSAction = new QAction (mRunningActions); 416 mVmTypeCABSAction->setIcon (VBoxGlobal::iconSet ( 417 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png")); 418 #endif 419 420 mVmTakeSnapshotAction = new QAction (mRunningOrPausedActions); 421 mVmTakeSnapshotAction->setIcon (VBoxGlobal::iconSet ( 422 ":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png")); 423 424 mVmShowInformationDlgAction = new QAction (this); 425 mVmShowInformationDlgAction->setIcon (VBoxGlobal::iconSet ( 426 ":/session_info_16px.png", ":/session_info_disabled_16px.png")); 427 428 mVmResetAction = new QAction (mRunningActions); 429 mVmResetAction->setIcon (VBoxGlobal::iconSet ( 430 ":/reset_16px.png", ":/reset_disabled_16px.png")); 431 432 mVmPauseAction = new QAction (this); 433 mVmPauseAction->setIcon (VBoxGlobal::iconSet ( 434 ":/pause_16px.png", ":/pause_disabled_16px.png")); 435 mVmPauseAction->setCheckable (true); 436 437 mVmACPIShutdownAction = new QAction (mRunningActions); 438 mVmACPIShutdownAction->setIcon (VBoxGlobal::iconSet ( 439 ":/acpi_16px.png", ":/acpi_disabled_16px.png")); 440 441 mVmCloseAction = new QAction (this); 442 mVmCloseAction->setMenuRole (QAction::QuitRole); 443 mVmCloseAction->setIcon (VBoxGlobal::iconSet (":/exit_16px.png")); 444 445 /* Devices menu actions */ 446 mDevicesNetworkDialogAction = new QAction (mRunningOrPausedActions); 447 mDevicesNetworkDialogAction->setIcon (VBoxGlobal::iconSet ( 448 ":/nw_16px.png", ":/nw_disabled_16px.png")); 449 450 mDevicesSFDialogAction = new QAction (mRunningOrPausedActions); 451 mDevicesSFDialogAction->setIcon (VBoxGlobal::iconSet ( 452 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")); 453 454 mDevicesSwitchVrdpAction = new QAction (mRunningOrPausedActions); 455 mDevicesSwitchVrdpAction->setIcon (VBoxGlobal::iconSetOnOff ( 456 ":/vrdp_on_16px.png", ":/vrdp_16px.png", 457 ":/vrdp_on_disabled_16px.png", ":/vrdp_disabled_16px.png")); 458 mDevicesSwitchVrdpAction->setCheckable (true); 459 460 mDevicesInstallGuestToolsAction = new QAction (mRunningActions); 461 mDevicesInstallGuestToolsAction->setIcon (VBoxGlobal::iconSet ( 462 ":/guesttools_16px.png", ":/guesttools_disabled_16px.png")); 463 464 #ifdef VBOX_WITH_DEBUGGER_GUI 465 /* Debug menu actions */ 466 if (vboxGlobal().isDebuggerEnabled()) 467 { 468 mDbgStatisticsAction = new QAction (this); 469 mDbgCommandLineAction = new QAction (this); 470 if (vboxGlobal().getDebuggerModule()== NIL_RTLDRMOD) 471 { 472 mDbgStatisticsAction->setEnabled (false); 473 mDbgCommandLineAction->setEnabled (false); 474 } 475 mDbgLoggingAction = new QAction (this); 476 mDbgLoggingAction->setCheckable (true); 477 } 478 else 479 { 480 mDbgStatisticsAction = 0; 481 mDbgCommandLineAction = 0; 482 mDbgLoggingAction = 0; 483 } 484 #endif 485 486 /* Help menu actions */ 487 mHelpActions.setup (this); 488 489 /* Menu Items */ 490 mMainMenu = new QIMenu (this); 491 mDevicesCDMenu = new QMenu (this); 492 mDevicesFDMenu = new QMenu (this); 493 mDevicesNetworkMenu = new QMenu (this); 494 mDevicesSFMenu = new QMenu (this); 495 mDevicesUSBMenu = new VBoxUSBMenu (this); 496 497 /* Machine submenu */ 498 mVMMenu = menuBar()->addMenu (QString::null); 499 mMainMenu->addMenu (mVMMenu); 500 mVmDisMouseIntegrMenu = new VBoxSwitchMenu (mVMMenu, mVmDisableMouseIntegrAction, true); 501 #if 0 /* TODO: Allow to setup status-bar! */ 502 mVmAutoresizeMenu = new VBoxSwitchMenu (mVMMenu, mVmAutoresizeGuestAction); 503 #endif 504 505 mVMMenu->addAction (mVmFullscreenAction); 506 mVMMenu->addAction (mVmSeamlessAction); 507 mVMMenu->addAction (mVmAutoresizeGuestAction); 508 mVMMenu->addAction (mVmAdjustWindowAction); 509 mVMMenu->addSeparator(); 510 mVMMenu->addAction (mVmDisableMouseIntegrAction); 511 mVMMenu->addSeparator(); 512 mVMMenu->addAction (mVmTypeCADAction); 513 #ifdef Q_WS_X11 514 mVMMenu->addAction (mVmTypeCABSAction); 515 #endif 516 mVMMenu->addSeparator(); 517 mVMMenu->addAction (mVmTakeSnapshotAction); 518 mVMMenu->addSeparator(); 519 mVMMenu->addAction (mVmShowInformationDlgAction); 520 mVMMenu->addSeparator(); 521 mVMMenu->addAction (mVmResetAction); 522 mVMMenu->addAction (mVmPauseAction); 523 mVMMenu->addAction (mVmACPIShutdownAction); 524 #ifndef Q_WS_MAC 525 mVMMenu->addSeparator(); 526 #endif /* Q_WS_MAC */ 527 mVMMenu->addAction (mVmCloseAction); 528 529 /* Devices submenu */ 530 mDevicesMenu = menuBar()->addMenu (QString::null); 531 mMainMenu->addMenu (mDevicesMenu); 532 533 mDevicesCDMenu->setIcon (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png")); 534 mDevicesFDMenu->setIcon (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png")); 535 mDevicesUSBMenu->setIcon (VBoxGlobal::iconSet (":/usb_16px.png", ":/usb_disabled_16px.png")); 536 537 mDevicesMenu->addMenu (mDevicesCDMenu); 538 mDevicesMenu->addMenu (mDevicesFDMenu); 539 mDevicesMenu->addAction (mDevicesNetworkDialogAction); 540 mDevicesMenu->addAction (mDevicesSFDialogAction); 541 mDevicesMenu->addMenu (mDevicesUSBMenu); 542 543 #if 0 /* TODO: Allow to setup status-bar! */ 544 mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, mDevicesSwitchVrdpAction); 545 #endif 546 mDevicesSwitchVrdpSeparator = mDevicesMenu->addSeparator(); 547 mDevicesMenu->addAction (mDevicesSwitchVrdpAction); 548 549 mDevicesMenu->addSeparator(); 550 mDevicesMenu->addAction (mDevicesInstallGuestToolsAction); 551 552 #ifdef VBOX_WITH_DEBUGGER_GUI 553 /* Debug submenu */ 554 if (vboxGlobal().isDebuggerEnabled()) 555 { 556 mDbgMenu = menuBar()->addMenu (QString::null); 557 mMainMenu->addMenu (mDbgMenu); 558 mDbgMenu->addAction (mDbgStatisticsAction); 559 mDbgMenu->addAction (mDbgCommandLineAction); 560 mDbgMenu->addAction (mDbgLoggingAction); 561 } 562 else 563 mDbgMenu = 0; 564 #endif 565 566 /* Help submenu */ 567 mHelpMenu = menuBar()->addMenu (QString::null); 568 mMainMenu->addMenu (mHelpMenu); 569 mHelpActions.addTo (mHelpMenu); 570 571 /* Machine submenu for mini-toolbar */ 572 mVMMenuMini = new QMenu (this); 573 mVMMenuMini->addAction (mVmTypeCADAction); 574 #ifdef Q_WS_X11 575 mVMMenuMini->addAction (mVmTypeCABSAction); 576 #endif 577 mVMMenuMini->addSeparator(); 578 mVMMenuMini->addAction (mVmTakeSnapshotAction); 579 mVMMenuMini->addSeparator(); 580 mVMMenuMini->addAction (mVmShowInformationDlgAction); 581 mVMMenuMini->addSeparator(); 582 mVMMenuMini->addAction (mVmResetAction); 583 mVMMenuMini->addAction (mVmPauseAction); 584 mVMMenuMini->addAction (mVmACPIShutdownAction); 585 586 /* Status bar */ 587 QWidget *indicatorBox = new QWidget; 588 QHBoxLayout *indicatorBoxHLayout = new QHBoxLayout (indicatorBox); 589 VBoxGlobal::setLayoutMargin (indicatorBoxHLayout, 0); 590 indicatorBoxHLayout->setSpacing (5); 591 592 /* i/o devices */ 593 mHDLed = new QIStateIndicator (KDeviceActivity_Idle); 594 mHDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/hd_16px.png")); 595 mHDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/hd_read_16px.png")); 596 mHDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/hd_write_16px.png")); 597 mHDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/hd_disabled_16px.png")); 598 indicatorBoxHLayout->addWidget (mHDLed); 599 mCDLed = new QIStateIndicator (KDeviceActivity_Idle); 600 mCDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/cd_16px.png")); 601 mCDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/cd_read_16px.png")); 602 mCDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/cd_write_16px.png")); 603 mCDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/cd_disabled_16px.png")); 604 indicatorBoxHLayout->addWidget (mCDLed); 605 #if 0 /* TODO: Allow to setup status-bar! */ 606 mFDLed = new QIStateIndicator (KDeviceActivity_Idle); 607 mFDLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/fd_16px.png")); 608 mFDLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/fd_read_16px.png")); 609 mFDLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/fd_write_16px.png")); 610 mFDLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/fd_disabled_16px.png")); 611 indicatorBoxHLayout->addWidget (mFDLed); 612 #endif 613 mNetLed = new QIStateIndicator (KDeviceActivity_Idle); 614 mNetLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/nw_16px.png")); 615 mNetLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/nw_read_16px.png")); 616 mNetLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/nw_write_16px.png")); 617 mNetLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/nw_disabled_16px.png")); 618 indicatorBoxHLayout->addWidget (mNetLed); 619 mUSBLed = new QIStateIndicator (KDeviceActivity_Idle); 620 mUSBLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/usb_16px.png")); 621 mUSBLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/usb_read_16px.png")); 622 mUSBLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/usb_write_16px.png")); 623 mUSBLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/usb_disabled_16px.png")); 624 indicatorBoxHLayout->addWidget (mUSBLed); 625 mSFLed = new QIStateIndicator (KDeviceActivity_Idle); 626 mSFLed->setStateIcon (KDeviceActivity_Idle, QPixmap (":/shared_folder_16px.png")); 627 mSFLed->setStateIcon (KDeviceActivity_Reading, QPixmap (":/shared_folder_read_16px.png")); 628 mSFLed->setStateIcon (KDeviceActivity_Writing, QPixmap (":/shared_folder_write_16px.png")); 629 mSFLed->setStateIcon (KDeviceActivity_Null, QPixmap (":/shared_folder_disabled_16px.png")); 630 indicatorBoxHLayout->addWidget (mSFLed); 631 632 /* virtualization */ 633 mVirtLed = new QIStateIndicator (0); 634 mVirtLed->setStateIcon (0, QPixmap (":/vtx_amdv_disabled_16px.png")); 635 mVirtLed->setStateIcon (1, QPixmap (":/vtx_amdv_16px.png")); 636 indicatorBoxHLayout->addWidget (mVirtLed); 637 638 QFrame *separator = new QFrame(); 639 separator->setFrameStyle (QFrame::VLine | QFrame::Sunken); 640 indicatorBoxHLayout->addWidget (separator); 641 642 /* mouse */ 643 mMouseLed = new QIStateIndicator (0); 644 mMouseLed->setStateIcon (0, QPixmap (":/mouse_disabled_16px.png")); 645 mMouseLed->setStateIcon (1, QPixmap (":/mouse_16px.png")); 646 mMouseLed->setStateIcon (2, QPixmap (":/mouse_seamless_16px.png")); 647 mMouseLed->setStateIcon (3, QPixmap (":/mouse_can_seamless_16px.png")); 648 mMouseLed->setStateIcon (4, QPixmap (":/mouse_can_seamless_uncaptured_16px.png")); 649 indicatorBoxHLayout->addWidget (mMouseLed); 650 651 /* host key */ 652 mHostkeyLedContainer = new QWidget; 653 QHBoxLayout *hostkeyLEDContainerLayout = new QHBoxLayout (mHostkeyLedContainer); 654 VBoxGlobal::setLayoutMargin (hostkeyLEDContainerLayout, 0); 655 hostkeyLEDContainerLayout->setSpacing (3); 656 indicatorBoxHLayout->addWidget (mHostkeyLedContainer); 657 658 mHostkeyLed = new QIStateIndicator (0); 659 mHostkeyLed->setStateIcon (0, QPixmap (":/hostkey_16px.png")); 660 mHostkeyLed->setStateIcon (1, QPixmap (":/hostkey_captured_16px.png")); 661 mHostkeyLed->setStateIcon (2, QPixmap (":/hostkey_pressed_16px.png")); 662 mHostkeyLed->setStateIcon (3, QPixmap (":/hostkey_captured_pressed_16px.png")); 663 hostkeyLEDContainerLayout->addWidget (mHostkeyLed); 664 mHostkeyName = new QLabel (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 665 hostkeyLEDContainerLayout->addWidget (mHostkeyName); 666 667 #if 0 /* TODO: Allow to setup status-bar! */ 668 /* VRDP Led */ 669 mVrdpLed = new QIStateIndicator (0, indicatorBox, "mVrdpLed", Qt::WNoAutoErase); 670 mVrdpLed->setStateIcon (0, QPixmap (":/vrdp_disabled_16px.png")); 671 mVrdpLed->setStateIcon (1, QPixmap (":/vrdp_16px.png")); 672 /* Auto-Resize LED */ 673 mAutoresizeLed = new QIStateIndicator (1, indicatorBox, "mAutoresizeLed", Qt::WNoAutoErase); 674 mAutoresizeLed->setStateIcon (0, QPixmap (":/auto_resize_off_disabled_16px.png")); 675 mAutoresizeLed->setStateIcon (1, QPixmap (":/auto_resize_off_16px.png")); 676 mAutoresizeLed->setStateIcon (2, QPixmap (":/auto_resize_on_disabled_16px.png")); 677 mAutoresizeLed->setStateIcon (3, QPixmap (":/auto_resize_on_16px.png")); 678 #endif 679 680 /* add to statusbar */ 681 statusBar()->addPermanentWidget (indicatorBox, 0); 682 683 /* Retranslate UI */ 684 retranslateUi(); 685 686 setWindowTitle (mCaptionPrefix); 687 688 /* Connections */ 689 connect (mVmFullscreenAction, SIGNAL (toggled (bool)), this, SLOT (vmFullscreen (bool))); 690 connect (mVmSeamlessAction, SIGNAL (toggled (bool)), this, SLOT (vmSeamless (bool))); 691 connect (mVmAutoresizeGuestAction, SIGNAL (toggled (bool)), this, SLOT (vmAutoresizeGuest (bool))); 692 connect (mVmAdjustWindowAction, SIGNAL (triggered()), this, SLOT (vmAdjustWindow())); 693 connect (mVmDisableMouseIntegrAction, SIGNAL (toggled (bool)), this, SLOT (vmDisableMouseIntegration (bool))); 694 connect (mVmTypeCADAction, SIGNAL (triggered()), this, SLOT (vmTypeCAD())); 695 #ifdef Q_WS_X11 696 connect (mVmTypeCABSAction, SIGNAL (triggered()), this, SLOT (vmTypeCABS())); 697 #endif 698 connect (mVmTakeSnapshotAction, SIGNAL (triggered()), this, SLOT (vmTakeSnapshot())); 699 connect (mVmShowInformationDlgAction, SIGNAL (triggered()), this, SLOT (vmShowInfoDialog())); 700 connect (mVmResetAction, SIGNAL (triggered()), this, SLOT (vmReset())); 701 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 702 connect (mVmACPIShutdownAction, SIGNAL (triggered()), this, SLOT (vmACPIShutdown())); 703 connect (mVmCloseAction, SIGNAL (triggered()), this, SLOT (vmClose())); 704 705 connect (mDevicesCDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 706 connect (mDevicesFDMenu, SIGNAL (aboutToShow()), this, SLOT (prepareStorageMenu())); 707 connect (mDevicesNetworkMenu, SIGNAL (aboutToShow()), this, SLOT (prepareNetworkMenu())); 708 connect (mDevicesSFMenu, SIGNAL (aboutToShow()), this, SLOT (prepareSFMenu())); 709 connect (mDevicesUSBMenu, SIGNAL(triggered (QAction *)), this, SLOT(switchUSB (QAction *))); 710 711 connect (mDevicesNetworkDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenNetworkDialog())); 712 connect (mDevicesSFDialogAction, SIGNAL (triggered()), this, SLOT (devicesOpenSFDialog())); 713 connect (mDevicesSwitchVrdpAction, SIGNAL (toggled (bool)), this, SLOT (devicesSwitchVrdp (bool))); 714 connect (mDevicesInstallGuestToolsAction, SIGNAL (triggered()), this, SLOT (devicesInstallGuestAdditions())); 715 716 connect (mCDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 717 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 718 #if 0 /* TODO: Allow to setup status-bar! */ 719 connect (mFDLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 720 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 721 #endif 722 connect (mNetLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 723 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 724 connect (mUSBLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 725 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 726 connect (mSFLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 727 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 728 connect (mMouseLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 729 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 730 #if 0 /* TODO: Allow to setup status-bar! */ 731 connect (mVrdpLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 732 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 733 connect (mAutoresizeLed, SIGNAL (contextMenuRequested (QIStateIndicator *, QContextMenuEvent *)), 734 this, SLOT (showIndicatorContextMenu (QIStateIndicator *, QContextMenuEvent *))); 735 #endif 736 737 /* Watch global settings changes */ 738 connect (&vboxGlobal().settings(), SIGNAL (propertyChanged (const char *, const char *)), 739 this, SLOT (processGlobalSettingChange (const char *, const char *))); 740 #ifdef Q_WS_MAC 741 connect (&vboxGlobal(), SIGNAL (dockIconUpdateChanged (const VBoxChangeDockIconUpdateEvent &)), 742 this, SLOT (changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &))); 743 connect (&vboxGlobal(), SIGNAL (presentationModeChanged (const VBoxChangePresentationModeEvent &)), 744 this, SLOT (changePresentationMode (const VBoxChangePresentationModeEvent &))); 745 #endif 746 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 if (mDbgMenu) 749 connect (mDbgMenu, SIGNAL (aboutToShow()), this, SLOT (dbgPrepareDebugMenu())); 750 if (mDbgStatisticsAction) 751 connect (mDbgStatisticsAction, SIGNAL (triggered()), this, SLOT (dbgShowStatistics())); 752 if (mDbgCommandLineAction) 753 connect (mDbgCommandLineAction, SIGNAL (triggered()), this, SLOT (dbgShowCommandLine())); 754 if (mDbgLoggingAction) 755 connect (mDbgLoggingAction, SIGNAL (toggled (bool)), this, SLOT (dbgLoggingToggled (bool))); 756 #endif 757 758 #ifdef Q_WS_MAC 759 /* For the status bar on Cocoa */ 760 setUnifiedTitleAndToolBarOnMac (true); 761 # ifdef VBOX_WITH_ICHAT_THEATER 762 // int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 }; 763 // HIWindowChangeAttributes (window, setAttr, 0); 764 initSharedAVManager(); 765 # endif 766 #endif 767 768 mMaskShift.scale (0, 0, Qt::IgnoreAspectRatio); 769 } 770 771 VBoxConsoleWnd::~VBoxConsoleWnd() 772 { 773 closeView(); 774 775 #ifdef VBOX_WITH_DEBUGGER_GUI 776 dbgDestroy(); 777 #endif 778 } 779 780 /** 781 * Opens a new console view to interact with a given VM. 782 * Does nothing if the console view is already opened. 783 * Used by VBoxGlobal::startMachine(), should not be called directly. 784 */ 785 bool VBoxConsoleWnd::openView (const CSession &aSession) 786 { 787 LogFlowFuncEnter(); 788 789 if (mConsole) 790 { 791 LogFlowFunc (("Already opened\n")); 792 LogFlowFuncLeave(); 793 return false; 794 } 795 796 #ifdef Q_WS_MAC 797 /* We have to make sure that we are getting the front most process. This is 798 * necessary for Qt versions > 4.3.3 */ 799 ProcessSerialNumber psn = { 0, kCurrentProcess }; 800 ::SetFrontProcess (&psn); 801 #endif /* Q_WS_MAC */ 802 803 mSession = aSession; 804 805 if (!centralWidget()) 806 { 807 setCentralWidget (new QWidget (this)); 808 QGridLayout *pMainLayout = new QGridLayout (centralWidget()); 809 VBoxGlobal::setLayoutMargin (pMainLayout, 0); 810 pMainLayout->setSpacing (0); 811 812 mShiftingSpacerLeft = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 813 mShiftingSpacerTop = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 814 mShiftingSpacerRight = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 815 mShiftingSpacerBottom = new QSpacerItem (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 816 pMainLayout->addItem (mShiftingSpacerTop, 0, 0, 1, -1); 817 pMainLayout->addItem (mShiftingSpacerLeft, 1, 0); 818 pMainLayout->addItem (mShiftingSpacerRight, 1, 2); 819 pMainLayout->addItem (mShiftingSpacerBottom, 2, 0, 1, -1); 820 } 821 822 mVmPauseAction->setChecked (false); 823 824 CConsole console = mSession.GetConsole(); 825 AssertWrapperOk (mSession); 826 827 CMachine machine = mSession.GetMachine(); 828 829 #ifdef VBOX_WITH_VIDEOHWACCEL 830 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled */ 831 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() 832 && VBoxGlobal::isAcceleration2DVideoAvailable() 833 ; 834 #endif 835 836 mConsole = new VBoxConsoleView (this, console, vboxGlobal().vmRenderMode(), 837 #ifdef VBOX_WITH_VIDEOHWACCEL 838 bAccelerate2DVideo, 839 #endif 840 centralWidget()); 841 qobject_cast <QGridLayout*> (centralWidget()->layout())->addWidget (mConsole, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 842 843 /* Mini toolbar */ 844 bool isActive = !(machine.GetExtraData (VBoxDefs::GUI_ShowMiniToolBar) == "no"); 845 bool isAtTop = (machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAlignment) == "top"); 846 bool isAutoHide = !(machine.GetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide) == "off"); 847 QList <QMenu*> menus (QList <QMenu*>() << mVMMenuMini << mDevicesMenu); 848 mMiniToolBar = new VBoxMiniToolBar (centralWidget(), isAtTop ? VBoxMiniToolBar::AlignTop : VBoxMiniToolBar::AlignBottom, 849 isActive, isAutoHide); 850 *mMiniToolBar << menus; 851 connect (mMiniToolBar, SIGNAL (exitAction()), this, SLOT (mtExitMode())); 852 connect (mMiniToolBar, SIGNAL (closeAction()), this, SLOT (mtCloseVM())); 853 connect (mMiniToolBar, SIGNAL (geometryUpdated()), this, SLOT (mtMaskUpdate())); 854 connect (this, SIGNAL (closing()), mMiniToolBar, SLOT (close())); 855 856 activateUICustomizations(); 857 858 /* Set the VM-specific application icon */ 859 /* Not on Mac OS X. The dock icon is handled below. */ 860 #ifndef Q_WS_MAC 861 setWindowIcon (vboxGlobal().vmGuestOSTypeIcon (machine.GetOSTypeId())); 862 #endif 863 864 /* Restore the position of the window and some options */ 865 { 866 QString str = machine.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 867 868 bool ok = false, max = false; 869 int x = 0, y = 0, w = 0, h = 0; 870 x = str.section (',', 0, 0).toInt (&ok); 871 if (ok) 872 y = str.section (',', 1, 1).toInt (&ok); 873 if (ok) 874 w = str.section (',', 2, 2).toInt (&ok); 875 if (ok) 876 h = str.section (',', 3, 3).toInt (&ok); 877 if (ok) 878 max = str.section (',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 879 880 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 881 QApplication::desktop()->availableGeometry (this); 882 883 if (ok /* previous parameters were read correctly */) 884 { 885 mNormalGeo = QRect (x, y, w, h); 886 setGeometry (mNormalGeo); 887 888 /* Normalize to the optimal size */ 889 mConsole->normalizeGeometry (true /* adjustPosition */); 890 891 if (max) 892 { 893 /* Maximize if needed */ 894 setWindowState (windowState() | Qt::WindowMaximized); 895 mWasMax = max; 896 } 897 } 898 else 899 { 900 /* Normalize to the optimal size */ 901 mConsole->normalizeGeometry (true /* adjustPosition */); 902 903 /* Move newly created window to the screen center. */ 904 mNormalGeo = geometry(); 905 mNormalGeo.moveCenter (ar.center()); 906 setGeometry (mNormalGeo); 907 } 908 909 show(); 910 911 /* Process show & possible maximize events */ 912 qApp->processEvents(); 913 914 mVmSeamlessAction->setEnabled (false); 915 str = machine.GetExtraData (VBoxDefs::GUI_Seamless); 916 if (str == "on") 917 mVmSeamlessAction->setChecked (true); 918 919 str = machine.GetExtraData (VBoxDefs::GUI_AutoresizeGuest); 920 if (str != "off") 921 mVmAutoresizeGuestAction->setChecked (true); 922 923 str = machine.GetExtraData (VBoxDefs::GUI_FirstRun); 924 if (str == "yes") 925 mIsFirstTimeStarted = true; 926 else if (!str.isEmpty()) 927 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 928 929 str = machine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime); 930 if (str == "no") 931 mIsAutoSaveMedia = false; 932 933 /* Check if one of extended modes to be activated on loading */ 934 QString fsMode = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 935 QString slMode = machine.GetExtraData (VBoxDefs::GUI_Seamless); 936 bool extendedMode = fsMode == "on" || slMode == "on"; 937 938 /* If one of extended modes to be loaded we have to ignore default 939 * console resize event which will come from VGA Device on loading. */ 940 if (extendedMode) 941 mConsole->requestToResize (QSize (w, h - menuBar()->height() - statusBar()->height())); 942 } 943 944 /* initialize storage stuff */ 945 int cdDevicesCount = 0; 946 int fdDevicesCount = 0; 947 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 948 foreach (const CMediumAttachment &attachment, attachments) 949 { 950 if (attachment.GetType() == KDeviceType_DVD) 951 ++ cdDevicesCount; 952 if (attachment.GetType() == KDeviceType_Floppy) 953 ++ fdDevicesCount; 954 } 955 mDevicesCDMenu->menuAction()->setData (cdDevicesCount); 956 mDevicesFDMenu->menuAction()->setData (fdDevicesCount); 957 mDevicesCDMenu->menuAction()->setVisible (cdDevicesCount); 958 mDevicesFDMenu->menuAction()->setVisible (fdDevicesCount); 959 960 /* initialize usb stuff */ 961 CUSBController usbctl = machine.GetUSBController(); 962 if (usbctl.isNull()) 963 { 964 /* hide usb_menu & usb_separator & usb_status_led */ 965 mDevicesUSBMenu->setVisible (false); 966 mUSBLed->setHidden (true); 967 } 968 else 969 { 970 bool isUSBEnabled = usbctl.GetEnabled(); 971 mDevicesUSBMenu->setEnabled (isUSBEnabled); 972 mDevicesUSBMenu->setConsole (console); 973 mUSBLed->setState (isUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null); 974 } 975 976 /* initialize vrdp stuff */ 977 CVRDPServer vrdpsrv = machine.GetVRDPServer(); 978 if (vrdpsrv.isNull()) 979 { 980 /* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */ 981 mDevicesSwitchVrdpAction->setVisible (false); 982 mDevicesSwitchVrdpSeparator->setVisible (false); 983 #if 0 /* TODO: Allow to setup status-bar! */ 984 mVrdpLed->setHidden (true); 985 #endif 986 } 987 988 /* start an idle timer that will update device lighths */ 989 connect (mIdleTimer, SIGNAL (timeout()), SLOT (updateDeviceLights())); 990 mIdleTimer->start (50); 991 992 connect (mConsole, SIGNAL (mouseStateChanged (int)), this, SLOT (updateMouseState (int))); 993 connect (mConsole, SIGNAL (keyboardStateChanged (int)), mHostkeyLed, SLOT (setState (int))); 994 connect (mConsole, SIGNAL (machineStateChanged (KMachineState)), this, SLOT (updateMachineState (KMachineState))); 995 connect (mConsole, SIGNAL (additionsStateChanged (const QString&, bool, bool, bool)), 996 this, SLOT (updateAdditionsState (const QString &, bool, bool, bool))); 997 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), 998 this, SLOT (updateMediaDriveState (VBoxDefs::MediumType))); 999 connect (mConsole, SIGNAL (usbStateChange()), this, SLOT (updateUsbState())); 1000 connect (mConsole, SIGNAL (networkStateChange()), this, SLOT (updateNetworkAdaptersState())); 1001 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateSharedFoldersState())); 1002 1003 #ifdef Q_WS_MAC 1004 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_RealtimeDockIconUpdateEnabled).toLower(); 1005 /* Default to true if it is an empty value */ 1006 bool f = (testStr.isEmpty() || testStr == "true"); 1007 mConsole->setDockIconEnabled (f); 1008 mConsole->updateDockOverlay(); 1009 #endif 1010 1011 /* set the correct initial mMachineState value */ 1012 mMachineState = console.GetState(); 1013 1014 mConsole->normalizeGeometry (false /* adjustPosition */); 1015 1016 updateAppearanceOf (AllStuff); 1017 1018 if (vboxGlobal().settings().autoCapture()) 1019 vboxProblem().remindAboutAutoCapture(); 1020 1021 /* 1022 * The further startup procedure should be done after we leave this method 1023 * and enter the main event loop in main(), because it may result into 1024 * showing various modal dialogs that will process events from within 1025 * this method that in turn can lead to various side effects like this 1026 * window is closed before this method returns, etc. 1027 */ 1028 1029 QTimer::singleShot (0, this, SLOT (finalizeOpenView())); 1030 1031 LogFlowFuncLeave(); 1032 return true; 1033 } 1034 1035 void VBoxConsoleWnd::setMouseIntegrationLocked (bool aDisabled) 1036 { 1037 mVmDisableMouseIntegrAction->setChecked (false); 1038 mVmDisableMouseIntegrAction->setEnabled (aDisabled); 1039 } 1040 1041 /** 1042 * Shows up and activates the popup version of the main menu. 1043 * 1044 * @param aCenter If @a true, center the popup menu on the screen, otherwise 1045 * show it at the current mouse pointer location. 1046 */ 1047 void VBoxConsoleWnd::popupMainMenu (bool aCenter) 1048 { 1049 QPoint pos = QCursor::pos(); 1050 if (aCenter) 1051 { 1052 QRect deskGeo = QApplication::desktop()->screenGeometry (this); 1053 QRect popGeo = mMainMenu->frameGeometry(); 1054 popGeo.moveCenter (QPoint (deskGeo.width() / 2, deskGeo.height() / 2)); 1055 pos = popGeo.topLeft(); 1056 } 1057 else 1058 { 1059 /* put the menu's bottom right corner to the pointer's hotspot point */ 1060 pos.setX (pos.x() - mMainMenu->frameGeometry().width()); 1061 pos.setY (pos.y() - mMainMenu->frameGeometry().height()); 1062 } 1063 1064 mMainMenu->popup (pos); 1065 mMainMenu->selectFirstAction(); 1066 #ifdef Q_WS_WIN 1067 mMainMenu->activateWindow(); 1068 #endif 1069 } 1070 1071 void VBoxConsoleWnd::installGuestAdditionsFrom (const QString &aSource) 1072 { 1073 CVirtualBox vbox = vboxGlobal().virtualBox(); 1074 QString uuid; 1075 1076 CMedium image = vbox.FindDVDImage (aSource); 1077 if (image.isNull()) 1078 { 1079 image = vbox.OpenDVDImage (aSource, uuid); 1080 if (vbox.isOk()) 1081 uuid = image.GetId(); 1082 } 1083 else 1084 uuid = image.GetId(); 1085 1086 if (!vbox.isOk()) 1087 return vboxProblem().cannotOpenMedium (this, vbox, VBoxDefs::MediumType_DVD, aSource); 1088 1089 Assert (!uuid.isNull()); 1090 CMachine m = mSession.GetMachine(); 1091 1092 QString ctrName; 1093 LONG ctrPort = -1, ctrDevice = -1; 1094 /* Searching for the first suitable slot */ 1095 { 1096 CStorageControllerVector controllers = m.GetStorageControllers(); 1097 int i = 0; 1098 while (i < controllers.size() && ctrName.isNull()) 1099 { 1100 CStorageController controller = controllers [i]; 1101 CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController (controller.GetName()); 1102 int j = 0; 1103 while (j < attachments.size() && ctrName.isNull()) 1104 { 1105 CMediumAttachment attachment = attachments [j]; 1106 if (attachment.GetType() == KDeviceType_DVD) 1107 { 1108 ctrName = controller.GetName(); 1109 ctrPort = attachment.GetPort(); 1110 ctrDevice = attachment.GetDevice(); 1111 } 1112 ++ j; 1113 } 1114 ++ i; 1115 } 1116 } 1117 1118 if (!ctrName.isNull()) 1119 { 1120 bool isMounted = false; 1121 1122 /* Mount medium to the predefined port/device */ 1123 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, false /* force */); 1124 if (m.isOk()) 1125 isMounted = true; 1126 else 1127 { 1128 /* Ask for force mounting */ 1129 if (vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, true /* retry? */) == QIMessageBox::Ok) 1130 { 1131 /* Force mount medium to the predefined port/device */ 1132 m.MountMedium (ctrName, ctrPort, ctrDevice, uuid, true /* force */); 1133 if (m.isOk()) 1134 isMounted = true; 1135 else 1136 vboxProblem().cannotRemountMedium (this, m, VBoxMedium (image, VBoxDefs::MediumType_DVD), true /* mount? */, false /* retry? */); 1137 } 1138 } 1139 1140 /* Save medium mounted at runtime */ 1141 if (isMounted && mIsAutoSaveMedia) 1142 { 1143 m.SaveSettings(); 1144 if (!m.isOk()) 1145 vboxProblem().cannotSaveMachineSettings (m); 1146 } 1147 } 1148 else 1149 vboxProblem().cannotMountGuestAdditions (m.GetName()); 1150 } 1151 1152 void VBoxConsoleWnd::setMask (const QRegion &aRegion) 1153 { 1154 QRegion region = aRegion; 1155 1156 /* The global mask shift cause of toolbars and such things. */ 1157 region.translate (mMaskShift.width(), mMaskShift.height()); 1158 1159 /* Including mini toolbar area */ 1160 QRegion toolBarRegion (mMiniToolBar->mask()); 1161 toolBarRegion.translate (mMiniToolBar->mapToGlobal (toolBarRegion.boundingRect().topLeft()) - QPoint (1, 0)); 1162 region += toolBarRegion; 1163 1164 /* Restrict the drawing to the available space on the screen. 1165 * (The &operator is better than the previous used -operator, 1166 * because this excludes space around the real screen also. 1167 * This is necessary for the mac.) */ 1168 region &= mStrictedRegion; 1169 1170 #ifdef Q_WS_WIN 1171 QRegion difference = mPrevRegion.subtract (region); 1172 1173 /* Region offset calculation */ 1174 int fleft = 0, ftop = 0; 1175 1176 /* Visible region calculation */ 1177 HRGN newReg = CreateRectRgn (0, 0, 0, 0); 1178 CombineRgn (newReg, region.handle(), 0, RGN_COPY); 1179 OffsetRgn (newReg, fleft, ftop); 1180 1181 /* Invisible region calculation */ 1182 HRGN diffReg = CreateRectRgn (0, 0, 0, 0); 1183 CombineRgn (diffReg, difference.handle(), 0, RGN_COPY); 1184 OffsetRgn (diffReg, fleft, ftop); 1185 1186 /* Set the current visible region and clean the previous */ 1187 SetWindowRgn (winId(), newReg, FALSE); 1188 RedrawWindow (0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 1189 RedrawWindow (mConsole->viewport()->winId(), 0, 0, RDW_INVALIDATE); 1190 1191 mPrevRegion = region; 1192 #elif defined (Q_WS_MAC) 1193 # if defined (VBOX_GUI_USE_QUARTZ2D) 1194 if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) 1195 { 1196 /* If we are using the Quartz2D backend we have to trigger 1197 * an repaint only. All the magic clipping stuff is done 1198 * in the paint engine. */ 1199 ::darwinWindowInvalidateShape (mConsole->viewport()); 1200 } 1201 else 1202 # endif 1203 { 1204 /* This is necessary to avoid the flicker by an mask update. 1205 * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html 1206 * for the hint. 1207 * There *must* be a better solution. */ 1208 if (!region.isEmpty()) 1209 region |= QRect (0, 0, 1, 1); 1210 // /* Save the current region for later processing in the darwin event handler. */ 1211 // mCurrRegion = region; 1212 // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately 1213 // * this command flushes a copy of the backbuffer to the screen after the new 1214 // * mask is set. This leads into a missplaced drawing of the content. Currently 1215 // * no alternative to this and also this is not 100% perfect. */ 1216 // repaint(); 1217 // qApp->processEvents(); 1218 // /* Now force the reshaping of the window. This is definitly necessary. */ 1219 // ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId())); 1220 QMainWindow::setMask (region); 1221 // HIWindowInvalidateShadow (::darwinToWindowRef (mConsole->viewport())); 1222 } 1223 #else 1224 QMainWindow::setMask (region); 1225 #endif 1226 } 1227 1228 void VBoxConsoleWnd::clearMask() 1229 { 1230 #ifdef Q_WS_WIN 1231 SetWindowRgn (winId(), 0, TRUE); 1232 #else 1233 QMainWindow::clearMask(); 1234 #endif 1235 } 1236 1237 void VBoxConsoleWnd::onDisplayResize (ulong aHeight, ulong aWidth) 1238 { 1239 if (mIsSeamless && QApplication::desktop()->availableGeometry (this).size() != QSize (aHeight, aWidth)) 1240 { 1241 mVmSeamlessAction->setChecked (false); 1242 /* should be cleared already, but just in case */ 1243 if (mIsSeamless) 1244 toggleFullscreenMode (false, true); 1245 } 1246 } 1247 1248 1249 bool VBoxConsoleWnd::event (QEvent *aEvent) 1250 { 1251 switch (aEvent->type()) 1252 { 1253 /* By handling every Resize and Move we keep track of the normal 1254 * (non-minimized and non-maximized) window geometry. Shame on Qt 1255 * that it doesn't provide this geometry in its public APIs. */ 1256 1257 case QEvent::Resize: 1258 { 1259 QResizeEvent *re = (QResizeEvent *) aEvent; 1260 1261 if (!mIsWaitingModeResize && !isWindowMaximized() && 1262 !isTrueFullscreen() && !isTrueSeamless()) 1263 { 1264 mNormalGeo.setSize (re->size()); 1265 #ifdef VBOX_WITH_DEBUGGER_GUI 1266 dbgAdjustRelativePos(); 1267 #endif 1268 } 1269 1270 if (mIsWaitingModeResize) 1271 { 1272 if (!mIsFullscreen && !mIsSeamless) 1273 { 1274 mIsWaitingModeResize = false; 1275 QTimer::singleShot (0, this, SLOT (onExitFullscreen())); 1276 } 1277 } 1278 break; 1279 } 1280 case QEvent::Move: 1281 { 1282 if (!isWindowMaximized() && !isTrueFullscreen() && !isTrueSeamless()) 1283 { 1284 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1285 #ifdef VBOX_WITH_DEBUGGER_GUI 1286 dbgAdjustRelativePos(); 529 // TODO: Update debugger window size! 530 //dbgAdjustRelativePos(); 1287 531 #endif 1288 532 } 1289 533 break; 1290 534 } 1291 #ifdef Q_WS_MAC 1292 case QEvent::Paint: 1293 { 1294 if (mIsSeamless) 535 case QEvent::Move: 536 { 537 if (!isMaximized()) 1295 538 { 1296 /* Clear the background */ 1297 CGContextClearRect (::darwinToCGContextRef (this), ::darwinToCGRect (frameGeometry())); 539 m_normalGeometry.moveTo(geometry().x(), geometry().y()); 540 #ifdef VBOX_WITH_DEBUGGER_GUI 541 // TODO: Update debugger window position! 542 //dbgAdjustRelativePos(); 543 #endif 1298 544 } 1299 545 break; 1300 546 } 1301 #endif1302 case StatusTipEvent::Type:1303 {1304 StatusTipEvent *ev = (StatusTipEvent*) aEvent;1305 statusBar()->showMessage (ev->mTip);1306 break;1307 }1308 547 default: 1309 548 break; 1310 549 } 1311 1312 return QMainWindow::event (aEvent); 1313 } 1314 1315 void VBoxConsoleWnd::closeEvent (QCloseEvent *aEvent) 1316 { 1317 LogFlowFuncEnter(); 1318 1319 static const char *kSave = "save"; 1320 static const char *kShutdown = "shutdown"; 1321 static const char *kPowerOff = "powerOff"; 1322 static const char *kDiscardCurState = "discardCurState"; 1323 1324 if (!mConsole) 1325 { 1326 aEvent->accept(); 1327 LogFlowFunc (("Console already destroyed!")); 1328 LogFlowFuncLeave(); 1329 return; 1330 } 1331 1332 switch (mMachineState) 1333 { 1334 case KMachineState_PoweredOff: 1335 case KMachineState_Saved: 1336 case KMachineState_Teleported: 1337 case KMachineState_Aborted: 1338 /* The machine has been already powered off or saved or aborted -- close the window immediately. */ 1339 aEvent->accept(); 1340 break; 1341 1342 default: 1343 /* The machine is in some temporary state like Saving or Stopping. 1344 * Ignore the close event. When it is Stopping, it will be soon closed anyway from updateMachineState(). 1345 * In all other cases, an appropriate progress dialog will be shown within a few seconds. */ 1346 aEvent->ignore(); 1347 break; 1348 1349 case KMachineState_Teleporting: /** @todo Live Migration: Test closing a VM that's being teleported or snapshotted. */ 1350 case KMachineState_LiveSnapshotting: 1351 case KMachineState_Running: 1352 case KMachineState_Paused: 1353 case KMachineState_TeleportingPausedVM: /** @todo Live Migration: Check out this. */ 1354 case KMachineState_Stuck: 1355 /* Start with ignoring the close event */ 1356 aEvent->ignore(); 1357 1358 bool isACPIEnabled = mSession.GetConsole().GetGuestEnteredACPIMode(); 1359 1360 bool success = true; 1361 1362 bool wasPaused = mMachineState == KMachineState_Paused 1363 || mMachineState == KMachineState_Stuck 1364 || mMachineState == KMachineState_TeleportingPausedVM; 1365 if (!wasPaused) 1366 { 1367 /* Suspend the VM and ignore the close event if failed to do so. 1368 * pause() will show the error message to the user. */ 1369 success = mConsole->pause (true); 1370 } 1371 1372 if (success) 1373 { 1374 success = false; 1375 1376 CMachine machine = mSession.GetMachine(); 1377 VBoxCloseVMDlg dlg (this); 1378 QString typeId = machine.GetOSTypeId(); 1379 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 1380 1381 /* Make the Discard checkbox invisible if there are no snapshots */ 1382 dlg.mCbDiscardCurState->setVisible (machine.GetSnapshotCount() > 0); 1383 if (!machine.GetCurrentSnapshot().isNull()) 1384 dlg.mCbDiscardCurState->setText (dlg.mCbDiscardCurState->text().arg (machine.GetCurrentSnapshot().GetName())); 1385 1386 if (mMachineState != KMachineState_Stuck) 1387 { 1388 /* Read the last user's choice for the given VM */ 1389 QStringList lastAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1390 AssertWrapperOk (machine); 1391 if (lastAction [0] == kSave) 1392 { 1393 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1394 dlg.mRbSave->setChecked (true); 1395 dlg.mRbSave->setFocus(); 1396 } 1397 else if (lastAction [0] == kPowerOff || !isACPIEnabled) 1398 { 1399 dlg.mRbShutdown->setEnabled (isACPIEnabled); 1400 dlg.mRbPowerOff->setChecked (true); 1401 dlg.mRbPowerOff->setFocus(); 1402 } 1403 else /* The default is ACPI Shutdown */ 1404 { 1405 dlg.mRbShutdown->setChecked (true); 1406 dlg.mRbShutdown->setFocus(); 1407 } 1408 dlg.mCbDiscardCurState->setChecked (lastAction.count() > 1 && lastAction [1] == kDiscardCurState); 1409 } 1410 else 1411 { 1412 /* The stuck VM can only be powered off; disable anything else and choose PowerOff */ 1413 dlg.mRbSave->setEnabled (false); 1414 dlg.mRbShutdown->setEnabled (false); 1415 dlg.mRbPowerOff->setChecked (true); 1416 } 1417 1418 bool wasShutdown = false; 1419 1420 if (dlg.exec() == QDialog::Accepted) 1421 { 1422 /* Disable auto closure because we want to have a chance to show 1423 * the error dialog on save state / power off failure. */ 1424 mNoAutoClose = true; 1425 1426 CConsole console = mConsole->console(); 1427 1428 if (dlg.mRbSave->isChecked()) 1429 { 1430 CProgress progress = console.SaveState(); 1431 1432 if (console.isOk()) 1433 { 1434 /* Show the "VM saving" progress dialog */ 1435 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1436 if (progress.GetResultCode() != 0) 1437 vboxProblem().cannotSaveMachineState (progress); 1438 else 1439 success = true; 1440 } 1441 else 1442 vboxProblem().cannotSaveMachineState (console); 1443 } 1444 else if (dlg.mRbShutdown->isChecked()) 1445 { 1446 /* Unpause the VM to let it grab the ACPI shutdown event */ 1447 mConsole->pause (false); 1448 /* Prevent the subsequent unpause request */ 1449 wasPaused = true; 1450 /* Signal ACPI shutdown (if there is no ACPI device, the 1451 * operation will fail) */ 1452 console.PowerButton(); 1453 wasShutdown = console.isOk(); 1454 if (!wasShutdown) 1455 vboxProblem().cannotACPIShutdownMachine (console); 1456 /* Success is always false because we never accept the close 1457 * window action when doing ACPI shutdown */ 1458 success = false; 1459 } 1460 else if (dlg.mRbPowerOff->isChecked()) 1461 { 1462 CProgress progress = console.PowerDown(); 1463 1464 if (console.isOk()) 1465 { 1466 /* Show the power down progress dialog */ 1467 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1468 if (progress.GetResultCode() != 0) 1469 vboxProblem().cannotStopMachine (progress); 1470 else 1471 success = true; 1472 } 1473 else 1474 vboxProblem().cannotStopMachine (console); 1475 1476 if (success) 1477 { 1478 /* Note: leave success = true even if we fail to 1479 * discard the current state later -- the console window 1480 * will closed anyway */ 1481 1482 /* Discard the current state if requested */ 1483 if (dlg.mCbDiscardCurState->isChecked() && dlg.mCbDiscardCurState->isVisibleTo (&dlg)) 1484 { 1485 CSnapshot snapshot = machine.GetCurrentSnapshot(); 1486 CProgress progress = console.RestoreSnapshot (snapshot); 1487 if (console.isOk()) 1488 { 1489 /* Show the progress dialog */ 1490 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1491 if (progress.GetResultCode() != 0) 1492 vboxProblem().cannotRestoreSnapshot (progress, snapshot.GetName()); 1493 } 1494 else 1495 vboxProblem().cannotRestoreSnapshot (console, snapshot.GetName()); 1496 } 1497 } 1498 } 1499 1500 if (success) 1501 { 1502 /* Accept the close action on success */ 1503 aEvent->accept(); 1504 } 1505 1506 if (success || wasShutdown) 1507 { 1508 /* Read the last user's choice for the given VM */ 1509 QStringList prevAction = machine.GetExtraData (VBoxDefs::GUI_LastCloseAction).split (','); 1510 /* Memorize the last user's choice for the given VM */ 1511 QString lastAction = kPowerOff; 1512 if (dlg.mRbSave->isChecked()) 1513 lastAction = kSave; 1514 else if (dlg.mRbShutdown->isChecked() || 1515 (dlg.mRbPowerOff->isChecked() && prevAction [0] == kShutdown && !isACPIEnabled)) 1516 lastAction = kShutdown; 1517 else if (dlg.mRbPowerOff->isChecked()) 1518 lastAction = kPowerOff; 1519 else 1520 AssertFailed(); 1521 if (dlg.mCbDiscardCurState->isChecked()) 1522 (lastAction += ",") += kDiscardCurState; 1523 machine.SetExtraData (VBoxDefs::GUI_LastCloseAction, lastAction); 1524 AssertWrapperOk (machine); 1525 } 1526 } 1527 } 1528 1529 mNoAutoClose = false; 1530 1531 if ( mMachineState == KMachineState_PoweredOff 1532 || mMachineState == KMachineState_Saved 1533 || mMachineState == KMachineState_Teleported 1534 || mMachineState == KMachineState_Aborted 1535 ) 1536 { 1537 /* The machine has been stopped while showing the Close or the Pause 1538 * failure dialog -- accept the close event immediately. */ 1539 aEvent->accept(); 1540 } 1541 else 1542 { 1543 if (!success) 1544 { 1545 /* Restore the running state if needed */ 1546 if (!wasPaused && mMachineState == KMachineState_Paused) 1547 mConsole->pause (false); 1548 } 1549 } 1550 break; 1551 } 1552 1553 if (aEvent->isAccepted()) 1554 { 1555 #ifndef VBOX_GUI_SEPARATE_VM_PROCESS 1556 vboxGlobal().selectorWnd().show(); 1557 #endif 1558 1559 /* Stop LED update timer */ 1560 mIdleTimer->stop(); 1561 mIdleTimer->disconnect (SIGNAL (timeout()), this, SLOT (updateDeviceLights())); 1562 1563 /* Hide console window */ 1564 hide(); 1565 1566 /* Save the position of the window and some options */ 1567 CMachine machine = mSession.GetMachine(); 1568 QString winPos = QString ("%1,%2,%3,%4") 1569 .arg (mNormalGeo.x()).arg (mNormalGeo.y()) 1570 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 1571 if (isWindowMaximized() || (mIsFullscreen && mWasMax) || (mIsSeamless && mWasMax)) 1572 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowPosition_Max); 1573 1574 machine.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 1575 1576 machine.SetExtraData (VBoxDefs::GUI_Fullscreen, 1577 mVmFullscreenAction->isChecked() ? "on" : "off"); 1578 machine.SetExtraData (VBoxDefs::GUI_Seamless, 1579 mVmSeamlessAction->isChecked() ? "on" : "off"); 1580 machine.SetExtraData (VBoxDefs::GUI_AutoresizeGuest, 1581 mVmAutoresizeGuestAction->isChecked() ? "on" : "off"); 1582 machine.SetExtraData (VBoxDefs::GUI_MiniToolBarAutoHide, 1583 mMiniToolBar->isAutoHide() ? "on" : "off"); 1584 1585 #ifdef VBOX_WITH_DEBUGGER_GUI 1586 /* Close & destroy the debugger GUI */ 1587 dbgDestroy(); 1588 #endif 1589 1590 /* Make sure all events are delievered */ 1591 qApp->processEvents(); 1592 1593 /* Notify all the top-level dialogs about closing */ 1594 emit closing(); 1595 } 1596 1597 LogFlowFunc (("accepted=%d\n", aEvent->isAccepted())); 1598 LogFlowFuncLeave(); 550 return QIWithRetranslateUI<QIMainDialog>::event(pEvent); 1599 551 } 1600 552 1601 553 #ifdef Q_WS_X11 1602 bool VBoxConsoleWnd::x11Event (XEvent *aEvent)554 bool UIMachineWindowNormal::x11Event(XEvent *pEvent) 1603 555 { 1604 556 /* Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut, … … 1607 559 * the mode in FocusOut X11 event structure to NotifyNormal to cause 1608 560 * Qt to process it as desired. */ 1609 if ( mConsole && aEvent->type == FocusOut)1610 { 1611 if ( aEvent->xfocus.mode == NotifyWhileGrabbed &&1612 ( aEvent->xfocus.detail == NotifyAncestor ||1613 aEvent->xfocus.detail == NotifyInferior ||1614 aEvent->xfocus.detail == NotifyNonlinear))1615 { 1616 aEvent->xfocus.mode = NotifyNormal;561 if (pEvent->type == FocusOut) 562 { 563 if (pEvent->xfocus.mode == NotifyWhileGrabbed && 564 (pEvent->xfocus.detail == NotifyAncestor || 565 pEvent->xfocus.detail == NotifyInferior || 566 pEvent->xfocus.detail == NotifyNonlinear)) 567 { 568 pEvent->xfocus.mode = NotifyNormal; 1617 569 } 1618 570 } … … 1621 573 #endif 1622 574 1623 /** 1624 * Sets the strings of the subwidgets using the current 1625 * language. 1626 */ 1627 void VBoxConsoleWnd::retranslateUi() 1628 { 1629 #ifdef VBOX_OSE 1630 mCaptionPrefix = tr ("VirtualBox OSE"); 1631 #else 1632 mCaptionPrefix = tr ("Sun VirtualBox"); 1633 #endif 1634 1635 #ifdef VBOX_BLEEDING_EDGE 1636 mCaptionPrefix += tr (" EXPERIMENTAL build %1r%2 - %3").arg (RTBldCfgVersion()).arg (RTBldCfgRevisionStr()).arg (VBOX_BLEEDING_EDGE); 1637 #endif 1638 /* 1639 * Note: All action shortcuts should be added to the menu text in the 1640 * form of "\tHost+<Key>" where <Key> is the shortcut key according 1641 * to regular QKeySequence rules. No translation of the "Host" word is 1642 * allowed (VBoxConsoleView relies on its spelling). setAccel() must not 1643 * be used. Unfortunately on the Mac the "host" string is silently removed 1644 * & the key is created as an global shortcut. So every e.g. F key stroke 1645 * in the vm leads to a menu call of the F entry. Mysteriously the 1646 * associated action isn't started. As a workaround the Host+<key> is 1647 * written in braces after the menu text. 1648 */ 1649 1650 /* VM actions */ 1651 #ifdef Q_WS_MAC 1652 qt_set_sequence_auto_mnemonic (false); 1653 #endif 1654 1655 mVmDisMouseIntegrMenu->setToolTip (tr ("Mouse Integration", "enable/disable...")); 1656 #if 0 /* TODO: Allow to setup status-bar! */ 1657 mVmAutoresizeMenu->setToolTip (tr ("Auto-resize Guest Display", "enable/disable...")); 1658 #endif 1659 1660 mVmFullscreenAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Fullscreen Mode"), "F")); 1661 mVmFullscreenAction->setStatusTip (tr ("Switch to fullscreen mode" )); 1662 1663 mVmSeamlessAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Seam&less Mode"), "L")); 1664 mVmSeamlessAction->setStatusTip (tr ("Switch to seamless desktop integration mode")); 1665 1666 mVmAutoresizeGuestAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Auto-resize &Guest Display"), "G")); 1667 mVmAutoresizeGuestAction->setStatusTip (tr ("Automatically resize the guest display when the " 1668 "window is resized (requires Guest Additions)")); 1669 1670 mVmAdjustWindowAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Adjust Window Size"), "A")); 1671 mVmAdjustWindowAction->setStatusTip (tr ("Adjust window size and position to best fit the guest display")); 1672 1673 /* mVmDisableMouseIntegrAction is set up in updateAppearanceOf() */ 1674 1675 mVmTypeCADAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Del"), "Del")); 1676 mVmTypeCADAction->setStatusTip (tr ("Send the Ctrl-Alt-Del sequence to the virtual machine")); 1677 1678 #if defined(Q_WS_X11) 1679 mVmTypeCABSAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Insert Ctrl-Alt-Backspace"), "Backspace")); 1680 mVmTypeCABSAction->setStatusTip (tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine")); 1681 #endif 1682 1683 mVmTakeSnapshotAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Take &Snapshot..."), "S")); 1684 mVmTakeSnapshotAction->setStatusTip (tr ("Take a snapshot of the virtual machine")); 1685 1686 mVmShowInformationDlgAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Session I&nformation Dialog"), "N")); 1687 mVmShowInformationDlgAction->setStatusTip (tr ("Show Session Information Dialog")); 1688 1689 mVmResetAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Reset"), "R")); 1690 mVmResetAction->setStatusTip (tr ("Reset the virtual machine")); 1691 1692 /* mVmPauseAction is set up in updateAppearanceOf() */ 1693 1694 #ifdef Q_WS_MAC 1695 /* Host+H is Hide on the mac */ 1696 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "U")); 1697 #else /* Q_WS_MAC */ 1698 mVmACPIShutdownAction->setText (VBoxGlobal::insertKeyToActionText (tr ("ACPI S&hutdown"), "H")); 1699 #endif /* !Q_WS_MAC */ 1700 mVmACPIShutdownAction->setStatusTip (tr ("Send the ACPI Power Button press event to the virtual machine")); 1701 1702 mVmCloseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Close..." ), "Q")); 1703 mVmCloseAction->setStatusTip (tr ("Close the virtual machine")); 1704 mVmCloseAction->setMenuRole (QAction::QuitRole); 1705 1706 /* Devices actions */ 1707 mDevicesCDMenu->setTitle (tr ("&CD/DVD Devices")); 1708 mDevicesFDMenu->setTitle (tr ("&Floppy Devices")); 1709 1710 mDevicesNetworkDialogAction->setText (tr ("&Network Adapters...")); 1711 mDevicesNetworkDialogAction->setStatusTip (tr ("Change the settings of network adapters")); 1712 1713 mDevicesSFDialogAction->setText (tr ("&Shared Folders...")); 1714 mDevicesSFDialogAction->setStatusTip (tr ("Create or modify shared folders")); 1715 1716 mDevicesSwitchVrdpAction->setText (tr ("&Remote Display")); 1717 mDevicesSwitchVrdpAction->setStatusTip (tr ("Enable or disable remote desktop (RDP) connections to this machine")); 1718 #if 0 /* TODO: Allow to setup status-bar! */ 1719 mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server", "enable/disable...")); 1720 #endif 1721 1722 mDevicesInstallGuestToolsAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Install Guest Additions..."), "D")); 1723 mDevicesInstallGuestToolsAction->setStatusTip (tr ("Mount the Guest Additions installation image")); 1724 1725 mDevicesUSBMenu->setTitle (tr ("&USB Devices")); 1726 1727 #ifdef VBOX_WITH_DEBUGGER_GUI 1728 /* Debug actions */ 1729 if (mDbgStatisticsAction) 1730 mDbgStatisticsAction->setText (tr ("&Statistics...", "debug action")); 1731 if (mDbgCommandLineAction) 1732 mDbgCommandLineAction->setText (tr ("&Command Line...", "debug action")); 1733 if (mDbgLoggingAction) 1734 mDbgLoggingAction->setText (tr ("&Logging...", "debug action")); 1735 #endif 1736 1737 /* Help actions */ 1738 mHelpActions.retranslateUi(); 1739 1740 /* Main menu & seamless popup menu */ 1741 mVMMenu->setTitle (tr ("&Machine")); 1742 // mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png")); 1743 1744 mVMMenuMini->setTitle (tr ("&Machine")); 1745 1746 mDevicesMenu->setTitle (tr ("&Devices")); 1747 // mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png")); 575 void UIMachineWindowNormal::prepareMenu() 576 { 577 /* Machine submenu: */ 578 QMenu *pMenuMachine = machineLogic()->actionsPool()->action(UIActionIndex_Menu_Machine)->menu(); 579 menuBar()->addMenu(pMenuMachine); 580 connect(pMenuMachine, SIGNAL(aboutToShow()), this, SLOT(sltPrepareMenuMachine())); 581 582 /* Devices submenu: */ 583 QMenu *pMenuDevices = machineLogic()->actionsPool()->action(UIActionIndex_Menu_Devices)->menu(); 584 menuBar()->addMenu(pMenuDevices); 585 connect(pMenuDevices, SIGNAL(aboutToShow()), this, SLOT(sltPrepareMenuDevices())); 1748 586 1749 587 #ifdef VBOX_WITH_DEBUGGER_GUI 1750 588 if (vboxGlobal().isDebuggerEnabled()) 1751 mDbgMenu->setTitle (tr ("De&bug")); 589 { 590 QMenu *pMenuDebug = machineLogic()->actionsPool()->action(UIActionIndex_Menu_Debug)->menu(); 591 menuBar()->addMenu(pMenuDebug); 592 connect(pMenuDebug, SIGNAL(aboutToShow()), this, SLOT(sltPrepareMenuDebug())); 593 } 1752 594 #endif 1753 mHelpMenu->setTitle (tr ("&Help")); 1754 // mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png")); 1755 1756 /* Status bar widgets */ 1757 mMouseLed->setToolTip ( 1758 tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>" 1759 "<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>" 1760 "<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>" 1761 "<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>" 1762 "<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>" 1763 "<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>" 1764 "Note that the mouse integration feature requires Guest Additions to be installed in the guest OS.")); 1765 mHostkeyLed->setToolTip ( 1766 tr ("Indicates whether the keyboard is captured by the guest OS " 1767 "(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>).")); 1768 mHostkeyName->setToolTip ( 1769 tr ("Shows the currently assigned Host key.<br>" 1770 "This key, when pressed alone, toggles the keyboard and mouse " 1771 "capture state. It can also be used in combination with other keys " 1772 "to quickly perform actions from the main menu.")); 1773 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 1774 1775 #if 0 /* TODO: Allow to setup status-bar! */ 1776 mAutoresizeLed->setToolTip ( 1777 tr ("Indicates whether the guest display auto-resize function is On " 1778 "(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). " 1779 "Note that this function requires Guest Additions to be installed in the guest OS.")); 595 } 596 597 void UIMachineWindowNormal::prepareStatusBar() 598 { 599 /* Common setup: */ 600 setStatusBar(new QIStatusBar(this)); 601 QWidget *pIndicatorBox = new QWidget; 602 QHBoxLayout *pIndicatorBoxHLayout = new QHBoxLayout(pIndicatorBox); 603 VBoxGlobal::setLayoutMargin(pIndicatorBoxHLayout, 0); 604 pIndicatorBoxHLayout->setSpacing(5); 605 606 /* Hard Disks: */ 607 pIndicatorBoxHLayout->addWidget(indicatorsPool()->indicator(UIIndicatorIndex_HardDisks)); 608 609 /* Optical Disks: */ 610 QIStateIndicator *pLedOpticalDisks = indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks); 611 pIndicatorBoxHLayout->addWidget(pLedOpticalDisks); 612 connect(pLedOpticalDisks, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)), 613 this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*))); 614 615 /* Network Adapters: */ 616 QIStateIndicator *pLedNetworkAdapters = indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters); 617 pIndicatorBoxHLayout->addWidget(pLedNetworkAdapters); 618 connect(pLedNetworkAdapters, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)), 619 this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*))); 620 621 /* USB Devices: */ 622 QIStateIndicator *pLedUSBDevices = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices); 623 pIndicatorBoxHLayout->addWidget(pLedUSBDevices); 624 connect(pLedUSBDevices, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)), 625 this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*))); 626 627 /* Shared Folders: */ 628 QIStateIndicator *pLedSharedFolders = indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders); 629 pIndicatorBoxHLayout->addWidget(pLedSharedFolders); 630 connect(pLedSharedFolders, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)), 631 this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*))); 632 633 /* Virtualization: */ 634 pIndicatorBoxHLayout->addWidget(indicatorsPool()->indicator(UIIndicatorIndex_Virtualization)); 635 636 /* Separator: */ 637 QFrame *pSeparator = new QFrame; 638 pSeparator->setFrameStyle(QFrame::VLine | QFrame::Sunken); 639 pIndicatorBoxHLayout->addWidget(pSeparator); 640 641 /* Mouse: */ 642 QIStateIndicator *pLedMouse = indicatorsPool()->indicator(UIIndicatorIndex_Mouse); 643 pIndicatorBoxHLayout->addWidget(pLedMouse); 644 connect(pLedMouse, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)), 645 this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*))); 646 647 /* Host Key: */ 648 m_pCntHostkey = new QWidget; 649 QHBoxLayout *pHostkeyLedContainerLayout = new QHBoxLayout(m_pCntHostkey); 650 VBoxGlobal::setLayoutMargin(pHostkeyLedContainerLayout, 0); 651 pHostkeyLedContainerLayout->setSpacing(3); 652 pIndicatorBoxHLayout->addWidget(m_pCntHostkey); 653 pHostkeyLedContainerLayout->addWidget(indicatorsPool()->indicator(UIIndicatorIndex_Hostkey)); 654 m_pNameHostkey = new QLabel(QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey())); 655 pHostkeyLedContainerLayout->addWidget(m_pNameHostkey); 656 657 /* Add to statusbar: */ 658 statusBar()->addPermanentWidget(pIndicatorBox, 0); 659 660 /* Create & start timer to update LEDs: */ 661 m_pIdleTimer = new QTimer(this); 662 connect(m_pIdleTimer, SIGNAL(timeout()), this, SLOT(sltUpdateIndicators())); 663 m_pIdleTimer->start(50); 664 665 #ifdef Q_WS_MAC 666 /* For the status bar on Cocoa: */ 667 setUnifiedTitleAndToolBarOnMac(true); 1780 668 #endif 1781 1782 updateAppearanceOf (AllStuff); 1783 } 1784 1785 void VBoxConsoleWnd::finalizeOpenView() 1786 { 1787 LogFlowFuncEnter(); 1788 1789 /* Notify the console scroll-view about the console-window is opened. */ 1790 mConsole->onViewOpened(); 1791 1792 bool saved = mMachineState == KMachineState_Saved; 1793 1794 CMachine machine = mSession.GetMachine(); 1795 CConsole console = mConsole->console(); 1796 1797 if (mIsFirstTimeStarted) 1798 { 1799 UIFirstRunWzd wzd (this, machine); 1800 wzd.exec(); 1801 1802 /* Remove GUI_FirstRun extra data key from the machine settings 1803 * file after showing the wizard once. */ 1804 machine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null); 1805 } 1806 1807 /* Start the VM */ 1808 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 1809 console.PowerUpPaused() : console.PowerUp(); 1810 1811 /* Check for an immediate failure */ 1812 if (!console.isOk()) 1813 { 1814 vboxProblem().cannotStartMachine (console); 1815 /* close this window (this will call closeView()) */ 1816 close(); 1817 1818 LogFlowFunc (("Error starting VM\n")); 1819 LogFlowFuncLeave(); 1820 return; 1821 } 1822 1823 mConsole->attach(); 1824 1825 /* Disable auto closure because we want to have a chance to show the 1826 * error dialog on startup failure */ 1827 mNoAutoClose = true; 1828 1829 /* show the "VM starting / restoring" progress dialog */ 1830 1831 if (saved) 1832 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 1833 else 1834 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this); 1835 1836 if (progress.GetResultCode() != 0) 1837 { 1838 vboxProblem().cannotStartMachine (progress); 1839 /* close this window (this will call closeView()) */ 1840 close(); 1841 1842 LogFlowFunc (("Error starting VM\n")); 1843 LogFlowFuncLeave(); 1844 return; 1845 } 1846 1847 mNoAutoClose = false; 1848 1849 /* Check if we missed a really quick termination after successful 1850 * startup, and process it if we did. */ 1851 if ( mMachineState == KMachineState_PoweredOff 1852 || mMachineState == KMachineState_Saved 1853 || mMachineState == KMachineState_Teleported 1854 || mMachineState == KMachineState_Aborted 1855 ) 1856 { 1857 close(); 1858 LogFlowFuncLeave(); 1859 return; 1860 } 1861 1862 /* Currently the machine is started and the guest API could be used... 1863 * Checking if the fullscreen mode should be activated */ 1864 QString str = machine.GetExtraData (VBoxDefs::GUI_Fullscreen); 1865 if (str == "on") 1866 mVmFullscreenAction->setChecked (true); 1867 1868 /* If seamless mode should be enabled then check if it is enabled 1869 * currently and re-enable it if seamless is supported */ 1870 if (mVmSeamlessAction->isChecked() && mIsSeamlessSupported && mIsGraphicsSupported) 1871 toggleFullscreenMode (true, true); 1872 #ifdef VBOX_WITH_DEBUGGER_GUI 1873 /* Open the debugger in "full screen" mode requested by the user. */ 1874 else if (vboxGlobal().isDebuggerAutoShowEnabled()) 1875 { 1876 /* console in upper left corner of the desktop. */ 1877 QRect rct (0, 0, 0, 0); 1878 QDesktopWidget *desktop = QApplication::desktop(); 1879 if (desktop) 1880 rct = desktop->availableGeometry(pos()); 1881 move (QPoint (rct.x(), rct.y())); 1882 1883 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled()) 1884 dbgShowStatistics(); 1885 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled()) 1886 dbgShowCommandLine(); 1887 1888 if (!vboxGlobal().isStartPausedEnabled()) 1889 mConsole->pause (false); 1890 } 669 } 670 671 void UIMachineWindowNormal::prepareConnections() 672 { 673 /* Setup global settings <-> indicators connections: */ 674 connect(&vboxGlobal().settings(), SIGNAL(propertyChanged(const char *, const char *)), 675 this, SLOT(sltProcessGlobalSettingChange(const char *, const char *))); 676 } 677 678 void UIMachineWindowNormal::prepareMachineView() 679 { 680 CMachine machine = machineLogic()->session().GetMachine(); 681 682 #ifdef VBOX_WITH_VIDEOHWACCEL 683 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled: */ 684 bool bAccelerate2DVideo = machine.GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable(); 1891 685 #endif 1892 686 1893 mIsOpenViewFinished = true; 1894 LogFlowFuncLeave(); 1895 1896 #ifdef VBOX_WITH_UPDATE_REQUEST 1897 vboxGlobal().showUpdateDialog (false /* aForce */); 687 m_pMachineView = UIMachineView::create( this 688 , vboxGlobal().vmRenderMode() // TODO: use correct variable here! 689 #ifdef VBOX_WITH_VIDEOHWACCEL 690 , bAccelerate2DVideo // TODO: use correct variable here! 1898 691 #endif 1899 1900 /* Finally check the status of required features. */ 1901 checkRequiredFeatures(); 1902 1903 /* Re-request all the static values finally after 1904 * view is really opened and attached. */ 1905 updateAppearanceOf (VirtualizationStuff); 1906 } 1907 1908 /** 1909 * Helper to safely close the main console window. 1910 * 1911 * This method ensures that close() will not be called if there is some 1912 * modal widget currently being executed, as it can cause uninitialization 1913 * at the point of code where it is not expected at all (example: 1914 * VBoxConsoleView::mouseEvent() calling 1915 * VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to 1916 * close the current modal widget is done and tryClose() is rescheduled for 1917 * later execution using a single-shot zero timer. 1918 * 1919 * In particular, this method is used by updateMachineState() when the VM 1920 * goes offline, which can even happen if we are inside the modal event loop, 1921 * (for example, the VM has been externally powered off or the guest OS 1922 * has initiated a shutdown procedure). 1923 */ 1924 void VBoxConsoleWnd::tryClose() 1925 { 1926 /* First close any open modal & popup widgets. Use a single shot with 1927 * timeout 0 to allow the widgets to cleany close and test then again. If 1928 * all open widgets are closed destroy ourself. */ 1929 QWidget *widget = QApplication::activeModalWidget() ? 1930 QApplication::activeModalWidget() : 1931 QApplication::activePopupWidget() ? 1932 QApplication::activePopupWidget() : 0; 1933 if (widget) 1934 { 1935 widget->close(); 1936 QTimer::singleShot (0, this, SLOT (tryClose())); 1937 } 1938 else 1939 close(); 1940 } 1941 1942 void VBoxConsoleWnd::vmFullscreen (bool aOn) 1943 { 1944 bool ok = toggleFullscreenMode (aOn, false /* aSeamless */); 1945 if (!ok) 1946 { 1947 /* On failure, restore the previous button state */ 1948 mVmFullscreenAction->blockSignals (true); 1949 mVmFullscreenAction->setChecked (!aOn); 1950 mVmFullscreenAction->blockSignals (false); 1951 } 1952 } 1953 1954 void VBoxConsoleWnd::vmSeamless (bool aOn) 1955 { 1956 /* Check if it is possible to enter/leave seamless mode */ 1957 if ((mIsSeamlessSupported && mIsGraphicsSupported) || !aOn) 1958 { 1959 bool ok = toggleFullscreenMode (aOn, true /* aSeamless */); 1960 if (!ok) 1961 { 1962 /* On failure, restore the previous button state */ 1963 mVmSeamlessAction->blockSignals (true); 1964 mVmSeamlessAction->setChecked (!aOn); 1965 mVmSeamlessAction->blockSignals (false); 1966 } 1967 } 1968 } 1969 1970 void VBoxConsoleWnd::vmAutoresizeGuest (bool on) 1971 { 1972 if (!mConsole) 1973 return; 1974 1975 #if 0 /* TODO: Allow to setup status-bar! */ 1976 mAutoresizeLed->setState (on ? 3 : 1); 1977 #endif 1978 1979 mConsole->setAutoresizeGuest (on); 1980 } 1981 1982 void VBoxConsoleWnd::vmAdjustWindow() 1983 { 1984 if (mConsole) 1985 { 1986 if (isWindowMaximized()) 1987 showNormal(); 1988 mConsole->normalizeGeometry (true /* adjustPosition */); 1989 } 1990 } 1991 1992 void VBoxConsoleWnd::vmDisableMouseIntegration (bool aOff) 1993 { 1994 if (mConsole) 1995 { 1996 mConsole->setMouseIntegrationEnabled (!aOff); 1997 updateAppearanceOf (DisableMouseIntegrAction); 1998 } 1999 } 2000 2001 void VBoxConsoleWnd::vmTypeCAD() 2002 { 2003 if (mConsole) 2004 { 2005 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2006 Assert (!keyboard.isNull()); 2007 keyboard.PutCAD(); 2008 AssertWrapperOk (keyboard); 2009 } 2010 } 2011 2012 #ifdef Q_WS_X11 2013 void VBoxConsoleWnd::vmTypeCABS() 2014 { 2015 if (mConsole) 2016 { 2017 CKeyboard keyboard = mConsole->console().GetKeyboard(); 2018 Assert (!keyboard.isNull()); 2019 static QVector <LONG> sSequence (6); 2020 sSequence[0] = 0x1d; // Ctrl down 2021 sSequence[1] = 0x38; // Alt down 2022 sSequence[2] = 0x0E; // Backspace down 2023 sSequence[3] = 0x8E; // Backspace up 2024 sSequence[4] = 0xb8; // Alt up 2025 sSequence[5] = 0x9d; // Ctrl up 2026 keyboard.PutScancodes (sSequence); 2027 AssertWrapperOk (keyboard); 2028 } 2029 } 2030 #endif 2031 2032 void VBoxConsoleWnd::vmTakeSnapshot() 2033 { 2034 AssertReturn (mConsole, (void) 0); 2035 2036 /* remember the paused state */ 2037 bool wasPaused = mMachineState == KMachineState_Paused; 2038 if (!wasPaused) 2039 { 2040 /* Suspend the VM and ignore the close event if failed to do so. 2041 * pause() will show the error message to the user. */ 2042 if (!mConsole->pause (true)) 2043 return; 2044 } 2045 2046 CMachine machine = mSession.GetMachine(); 2047 2048 VBoxTakeSnapshotDlg dlg (this, machine); 2049 2050 QString typeId = machine.GetOSTypeId(); 2051 dlg.mLbIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId)); 2052 2053 /* search for the max available filter index */ 2054 QString nameTemplate = tr ("Snapshot %1"); 2055 int maxSnapshotIndex = searchMaxSnapshotIndex (machine, machine.GetSnapshot (QString()), nameTemplate); 2056 dlg.mLeName->setText (nameTemplate.arg (++ maxSnapshotIndex)); 2057 2058 if (dlg.exec() == QDialog::Accepted) 2059 { 2060 CConsole console = mSession.GetConsole(); 2061 2062 CProgress progress = console.TakeSnapshot (dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText()); 2063 2064 if (console.isOk()) 2065 { 2066 /* Show the "Taking Snapshot" progress dialog */ 2067 vboxProblem().showModalProgressDialog (progress, machine.GetName(), this, 0); 2068 2069 if (progress.GetResultCode() != 0) 2070 vboxProblem().cannotTakeSnapshot (progress); 692 , machineLogic()->visualStateType()); 693 qobject_cast<QGridLayout*>(centralWidget()->layout())->addWidget(m_pMachineView, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter); 694 695 /* Setup machine view <-> indicators connections: */ 696 connect(machineView(), SIGNAL(keyboardStateChanged(int)), 697 indicatorsPool()->indicator(UIIndicatorIndex_Hostkey), SLOT(setState(int))); 698 // TODO: Update these 5 indicators through indicators pool! 699 connect(machineView(), SIGNAL(mediaDriveChanged(VBoxDefs::MediumType)), 700 this, SLOT(sltUpdateMediaDriveState(VBoxDefs::MediumType))); 701 connect(machineView(), SIGNAL(networkStateChange()), this, SLOT(sltUpdateNetworkAdaptersState())); 702 connect(machineView(), SIGNAL(usbStateChange()), this, SLOT(sltUpdateUsbState())); 703 connect(machineView(), SIGNAL(sharedFoldersChanged()), this, SLOT(sltUpdateSharedFoldersState())); 704 connect(machineView(), SIGNAL(mouseStateChanged(int)), this, SLOT(sltUpdateMouseState(int))); 705 } 706 707 void UIMachineWindowNormal::loadWindowSettings() 708 { 709 CMachine machine = machineLogic()->session().GetMachine(); 710 711 /* Extra-data settings */ 712 { 713 QString strPositionSettings = machine.GetExtraData(VBoxDefs::GUI_LastWindowPosition); 714 715 bool ok = false, max = false; 716 int x = 0, y = 0, w = 0, h = 0; 717 x = strPositionSettings.section(',', 0, 0).toInt(&ok); 718 if (ok) 719 y = strPositionSettings.section(',', 1, 1).toInt(&ok); 720 if (ok) 721 w = strPositionSettings.section(',', 2, 2).toInt(&ok); 722 if (ok) 723 h = strPositionSettings.section(',', 3, 3).toInt(&ok); 724 if (ok) 725 max = strPositionSettings.section(',', 4, 4) == VBoxDefs::GUI_LastWindowPosition_Max; 726 727 QRect ar = ok ? QApplication::desktop()->availableGeometry(QPoint(x, y)) : 728 QApplication::desktop()->availableGeometry(machineWindow()); 729 730 if (ok /* if previous parameters were read correctly */) 731 { 732 m_normalGeometry = QRect(x, y, w, h); 733 setGeometry(m_normalGeometry); 734 735 /* Normalize to the optimal size */ 736 machineView()->normalizeGeometry(true /* adjust position? */); 737 738 /* Maximize if needed */ 739 if (max) 740 setWindowState(windowState() | Qt::WindowMaximized); 2071 741 } 2072 742 else 2073 vboxProblem().cannotTakeSnapshot (console); 2074 } 2075 2076 /* Restore the running state if needed */ 2077 if (!wasPaused) 2078 mConsole->pause (false); 2079 } 2080 2081 void VBoxConsoleWnd::vmShowInfoDialog() 2082 { 2083 VBoxVMInformationDlg::createInformationDlg (mSession, mConsole); 2084 } 2085 2086 void VBoxConsoleWnd::vmReset() 2087 { 2088 if (mConsole) 2089 { 2090 if (vboxProblem().confirmVMReset (this)) 2091 mConsole->console().Reset(); 2092 } 2093 } 2094 2095 void VBoxConsoleWnd::vmPause (bool aOn) 2096 { 2097 if (mConsole) 2098 { 2099 mConsole->pause (aOn); 2100 updateAppearanceOf (PauseAction); 2101 } 2102 } 2103 2104 void VBoxConsoleWnd::vmACPIShutdown() 2105 { 2106 if (!mSession.GetConsole().GetGuestEnteredACPIMode()) 2107 return vboxProblem().cannotSendACPIToMachine(); 2108 2109 if (mConsole) 2110 { 2111 CConsole console = mConsole->console(); 2112 console.PowerButton(); 2113 if (!console.isOk()) 2114 vboxProblem().cannotACPIShutdownMachine (console); 2115 } 2116 } 2117 2118 void VBoxConsoleWnd::vmClose() 2119 { 2120 if (mConsole) 2121 close(); 2122 } 2123 2124 void VBoxConsoleWnd::devicesSwitchVrdp (bool aOn) 2125 { 2126 if (!mConsole) return; 2127 2128 CVRDPServer vrdpServer = mSession.GetMachine().GetVRDPServer(); 2129 /* This method should not be executed if vrdpServer is null */ 2130 Assert (!vrdpServer.isNull()); 2131 2132 vrdpServer.SetEnabled (aOn); 2133 updateAppearanceOf (VRDPStuff); 2134 } 2135 2136 void VBoxConsoleWnd::devicesOpenNetworkDialog() 2137 { 2138 if (!mConsole) return; 2139 2140 VBoxNetworkDialog dlg (mConsole, mSession); 2141 dlg.exec(); 2142 } 2143 2144 void VBoxConsoleWnd::devicesOpenSFDialog() 2145 { 2146 if (!mConsole) return; 2147 2148 VBoxSFDialog dlg (mConsole, mSession); 2149 dlg.exec(); 2150 } 2151 2152 void VBoxConsoleWnd::devicesInstallGuestAdditions() 2153 { 2154 char szAppPrivPath [RTPATH_MAX]; 2155 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); 2156 AssertRC (rc); 2157 2158 QString src1 = QString (szAppPrivPath) + "/VBoxGuestAdditions.iso"; 2159 QString src2 = qApp->applicationDirPath() + "/additions/VBoxGuestAdditions.iso"; 2160 2161 /* Check the standard image locations */ 2162 if (QFile::exists (src1)) 2163 return installGuestAdditionsFrom (src1); 2164 else if (QFile::exists (src2)) 2165 return installGuestAdditionsFrom (src2); 2166 2167 /* Check for the already registered image */ 2168 CVirtualBox vbox = vboxGlobal().virtualBox(); 2169 QString name = QString ("VBoxGuestAdditions_%1.iso").arg (vbox.GetVersion().remove ("_OSE")); 2170 2171 CMediumVector vec = vbox.GetDVDImages(); 2172 for (CMediumVector::ConstIterator it = vec.begin(); it != vec.end(); ++ it) 2173 { 2174 QString path = it->GetLocation(); 2175 /* Compare the name part ignoring the file case */ 2176 QString fn = QFileInfo (path).fileName(); 2177 if (RTPathCompare (name.toUtf8().constData(), fn.toUtf8().constData()) == 0) 2178 return installGuestAdditionsFrom (path); 2179 } 2180 2181 /* Download the required image */ 2182 int result = vboxProblem().cannotFindGuestAdditions ( 2183 QDir::toNativeSeparators (src1), QDir::toNativeSeparators (src2)); 2184 if (result == QIMessageBox::Yes) 2185 { 2186 QString source = QString ("http://download.virtualbox.org/virtualbox/%1/") 2187 .arg (vbox.GetVersion().remove ("_OSE")) + name; 2188 QString target = QDir (vboxGlobal().virtualBox().GetHomeFolder()) 2189 .absoluteFilePath (name); 2190 2191 VBoxAdditionsDownloader *dl = 2192 new VBoxAdditionsDownloader (source, target, mDevicesInstallGuestToolsAction); 2193 statusBar()->addWidget (dl, 0); 2194 dl->start(); 2195 } 2196 } 2197 2198 void VBoxConsoleWnd::prepareStorageMenu() 2199 { 2200 QMenu *menu = qobject_cast <QMenu*> (sender()); 2201 Assert (menu); 2202 menu->clear(); 2203 2204 KDeviceType deviceType = menu == mDevicesCDMenu ? KDeviceType_DVD : 2205 menu == mDevicesFDMenu ? KDeviceType_Floppy : 2206 KDeviceType_Null; 2207 Assert (deviceType != KDeviceType_Null); 2208 2209 VBoxDefs::MediumType mediumType = menu == mDevicesCDMenu ? VBoxDefs::MediumType_DVD : 2210 menu == mDevicesFDMenu ? VBoxDefs::MediumType_Floppy : 2211 VBoxDefs::MediumType_Invalid; 2212 Assert (mediumType != VBoxDefs::MediumType_Invalid); 2213 2214 CMachine machine = mSession.GetMachine(); 2215 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments(); 2216 foreach (const CMediumAttachment &attachment, attachments) 2217 { 2218 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 2219 if ( !controller.isNull() 2220 && (attachment.GetType() == deviceType)) 2221 { 2222 /* Attachment menu item */ 2223 QMenu *attachmentMenu = 0; 2224 if (menu->menuAction()->data().toInt() > 1) 2225 { 2226 attachmentMenu = new QMenu (menu); 2227 attachmentMenu->setTitle (QString ("%1 (%2)").arg (controller.GetName()) 2228 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), 2229 attachment.GetPort(), 2230 attachment.GetDevice())))); 2231 switch (controller.GetBus()) 2232 { 2233 case KStorageBus_IDE: 2234 attachmentMenu->setIcon (QIcon (":/ide_16px.png")); break; 2235 case KStorageBus_SATA: 2236 attachmentMenu->setIcon (QIcon (":/sata_16px.png")); break; 2237 case KStorageBus_SCSI: 2238 attachmentMenu->setIcon (QIcon (":/scsi_16px.png")); break; 2239 case KStorageBus_Floppy: 2240 attachmentMenu->setIcon (QIcon (":/floppy_16px.png")); break; 2241 default: 2242 break; 2243 } 2244 menu->addMenu (attachmentMenu); 2245 } 2246 else attachmentMenu = menu; 2247 2248 /* Mount Medium actions */ 2249 CMediumVector mediums; 2250 switch (mediumType) 2251 { 2252 case VBoxDefs::MediumType_DVD: 2253 mediums += vboxGlobal().virtualBox().GetHost().GetDVDDrives(); 2254 mediums += vboxGlobal().virtualBox().GetDVDImages(); 2255 break; 2256 case VBoxDefs::MediumType_Floppy: 2257 mediums += vboxGlobal().virtualBox().GetHost().GetFloppyDrives(); 2258 mediums += vboxGlobal().virtualBox().GetFloppyImages(); 2259 break; 2260 default: 2261 break; 2262 } 2263 2264 int mediumsToBeShown = 0; 2265 const int maxMediumsToBeShown = 5; 2266 CMedium currentMedium = attachment.GetMedium(); 2267 QString currentId = currentMedium.isNull() ? QString::null : currentMedium.GetId(); 2268 bool currentUsed = false; 2269 foreach (CMedium medium, mediums) 2270 { 2271 bool isMediumUsed = false; 2272 foreach (const CMediumAttachment &otherAttachment, attachments) 2273 { 2274 if (otherAttachment != attachment) 2275 { 2276 CMedium otherMedium = otherAttachment.GetMedium(); 2277 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 2278 { 2279 isMediumUsed = true; 2280 break; 2281 } 2282 } 2283 } 2284 if (!isMediumUsed) 2285 { 2286 if (!currentUsed && !currentMedium.isNull() && mediumsToBeShown == maxMediumsToBeShown - 1) 2287 medium = currentMedium; 2288 2289 if (medium.GetId() == currentId) 2290 currentUsed = true; 2291 2292 QAction *mountMediumAction = new QAction (VBoxMedium (medium, mediumType).name(), attachmentMenu); 2293 mountMediumAction->setCheckable (true); 2294 mountMediumAction->setChecked (!currentMedium.isNull() && medium.GetId() == currentId); 2295 mountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2296 attachment.GetPort(), 2297 attachment.GetDevice(), 2298 medium.GetId()))); 2299 connect (mountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2300 attachmentMenu->addAction (mountMediumAction); 2301 ++ mediumsToBeShown; 2302 if (mediumsToBeShown == maxMediumsToBeShown) 2303 break; 2304 } 2305 } 2306 2307 /* Virtual Media Manager action */ 2308 QAction *callVMMAction = new QAction (attachmentMenu); 2309 callVMMAction->setIcon (QIcon (":/diskimage_16px.png")); 2310 callVMMAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2311 attachment.GetPort(), 2312 attachment.GetDevice(), 2313 mediumType))); 2314 connect (callVMMAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2315 attachmentMenu->addAction (callVMMAction); 2316 2317 /* Separator */ 2318 attachmentMenu->addSeparator(); 2319 2320 /* Unmount Medium action */ 2321 QAction *unmountMediumAction = new QAction (attachmentMenu); 2322 unmountMediumAction->setEnabled (!currentMedium.isNull()); 2323 unmountMediumAction->setData (QVariant::fromValue (MountTarget (controller.GetName(), 2324 attachment.GetPort(), 2325 attachment.GetDevice()))); 2326 connect (unmountMediumAction, SIGNAL (triggered (bool)), this, SLOT (mountMedium())); 2327 attachmentMenu->addAction (unmountMediumAction); 2328 2329 /* Switch CD/FD naming */ 2330 switch (mediumType) 2331 { 2332 case VBoxDefs::MediumType_DVD: 2333 callVMMAction->setText (tr ("More CD/DVD Images...")); 2334 unmountMediumAction->setText (tr ("Unmount CD/DVD Device")); 2335 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/cd_unmount_16px.png", 2336 ":/cd_unmount_dis_16px.png")); 2337 break; 2338 case VBoxDefs::MediumType_Floppy: 2339 callVMMAction->setText (tr ("More Floppy Images...")); 2340 unmountMediumAction->setText (tr ("Unmount Floppy Device")); 2341 unmountMediumAction->setIcon (VBoxGlobal::iconSet (":/fd_unmount_16px.png", 2342 ":/fd_unmount_dis_16px.png")); 2343 break; 2344 default: 2345 break; 2346 } 2347 } 2348 } 2349 2350 if (menu->menuAction()->data().toInt() == 0) 2351 { 2352 /* Empty menu item */ 2353 Assert (menu->isEmpty()); 2354 QAction *emptyMenuAction = new QAction (menu); 2355 emptyMenuAction->setEnabled (false); 2356 switch (mediumType) 2357 { 2358 case VBoxDefs::MediumType_DVD: 2359 emptyMenuAction->setText (tr ("No CD/DVD Devices Attached")); 2360 break; 2361 case VBoxDefs::MediumType_Floppy: 2362 emptyMenuAction->setText (tr ("No Floppy Devices Attached")); 2363 break; 2364 default: 2365 break; 2366 } 2367 emptyMenuAction->setIcon (VBoxGlobal::iconSet (":/delete_16px.png", ":/delete_dis_16px.png")); 2368 menu->addAction (emptyMenuAction); 2369 } 2370 } 2371 2372 void VBoxConsoleWnd::prepareNetworkMenu() 2373 { 2374 mDevicesNetworkMenu->clear(); 2375 mDevicesNetworkMenu->addAction (mDevicesNetworkDialogAction); 2376 } 2377 2378 void VBoxConsoleWnd::prepareSFMenu() 2379 { 2380 mDevicesSFMenu->clear(); 2381 mDevicesSFMenu->addAction (mDevicesSFDialogAction); 2382 } 2383 2384 void VBoxConsoleWnd::mountMedium() 2385 { 2386 /* Get sender action */ 2387 QAction *action = qobject_cast <QAction*> (sender()); 2388 Assert (action); 2389 2390 /* Get current machine */ 2391 CMachine machine = mSession.GetMachine(); 2392 2393 /* Get mount-target */ 2394 MountTarget target = action->data().value <MountTarget>(); 2395 2396 /* Current mount-target attributes */ 2397 CMediumAttachment currentAttachment = machine.GetMediumAttachment (target.name, target.port, target.device); 2398 CMedium currentMedium = currentAttachment.GetMedium(); 2399 QString currentId = currentMedium.isNull() ? QString ("") : currentMedium.GetId(); 2400 2401 /* New mount-target attributes */ 2402 QString newId = QString (""); 2403 bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid; 2404 2405 /* Open Virtual Media Manager to select image id */ 2406 if (selectWithMediaManager) 2407 { 2408 /* Search for already used images */ 2409 QStringList usedImages; 2410 foreach (const CMediumAttachment &attachment, machine.GetMediumAttachments()) 2411 { 2412 CMedium medium = attachment.GetMedium(); 2413 if (attachment != currentAttachment && !medium.isNull() && !medium.GetHostDrive()) 2414 usedImages << medium.GetId(); 2415 } 2416 /* Open VMM Dialog */ 2417 VBoxMediaManagerDlg dlg (this); 2418 dlg.setup (target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages); 2419 if (dlg.exec() == QDialog::Accepted) 2420 newId = dlg.selectedId(); 2421 else return; 2422 } 2423 /* Use medium which was sent */ 2424 else if (!target.id.isNull() && target.id != currentId) 2425 newId = target.id; 2426 2427 bool mount = !newId.isEmpty(); 2428 2429 /* Remount medium to the predefined port/device */ 2430 bool wasMounted = false; 2431 machine.MountMedium (target.name, target.port, target.device, newId, false /* force */); 2432 if (machine.isOk()) 2433 wasMounted = true; 2434 else 2435 { 2436 /* Ask for force remounting */ 2437 if (vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok) 2438 { 2439 /* Force remount medium to the predefined port/device. */ 2440 machine.MountMedium (target.name, target.port, target.device, newId, true /* force */); 2441 if (machine.isOk()) 2442 wasMounted = true; 2443 else 2444 vboxProblem().cannotRemountMedium (this, machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, false /* retry? */); 2445 } 2446 } 2447 2448 /* Save medium mounted at runtime */ 2449 if (wasMounted && mIsAutoSaveMedia) 2450 { 2451 machine.SaveSettings(); 2452 if (!machine.isOk()) 2453 vboxProblem().cannotSaveMachineSettings (machine); 2454 } 2455 } 2456 2457 /** 2458 * Attach/Detach selected USB Device. 2459 */ 2460 void VBoxConsoleWnd::switchUSB (QAction *aAction) 2461 { 2462 if (!mConsole) return; 2463 2464 CConsole console = mSession.GetConsole(); 2465 AssertWrapperOk (mSession); 2466 2467 CUSBDevice usb = mDevicesUSBMenu->getUSB (aAction); 2468 /* if null then some other item but a USB device is selected */ 2469 if (usb.isNull()) 2470 return; 2471 2472 if (!aAction->isChecked()) 2473 { 2474 console.DetachUSBDevice (usb.GetId()); 2475 if (!console.isOk()) 2476 { 2477 /// @todo (r=dmik) the dialog should be either modeless 2478 // or we have to pause the VM 2479 vboxProblem().cannotDetachUSBDevice (console, vboxGlobal().details (usb)); 2480 } 2481 } 2482 else 2483 { 2484 console.AttachUSBDevice (usb.GetId()); 2485 if (!console.isOk()) 2486 { 2487 /// @todo (r=dmik) the dialog should be either modeless 2488 // or we have to pause the VM 2489 vboxProblem().cannotAttachUSBDevice (console, vboxGlobal().details (usb)); 2490 } 2491 } 2492 } 2493 2494 void VBoxConsoleWnd::showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent) 2495 { 2496 if (aInd == mCDLed) 2497 { 2498 mDevicesCDMenu->exec (aEvent->globalPos()); 2499 } 2500 #if 0 /* TODO: Allow to setup status-bar! */ 2501 else if (aInd == mFDLed) 2502 { 2503 mDevicesFDMenu->exec (aEvent->globalPos()); 2504 } 2505 #endif 2506 else if (aInd == mNetLed) 2507 { 2508 if (mDevicesNetworkMenu->isEnabled()) 2509 mDevicesNetworkMenu->exec (aEvent->globalPos()); 2510 } 2511 else if (aInd == mUSBLed) 2512 { 2513 if (mDevicesUSBMenu->isEnabled()) 2514 mDevicesUSBMenu->exec (aEvent->globalPos()); 2515 } 2516 else if (aInd == mSFLed) 2517 { 2518 if (mDevicesSFMenu->isEnabled()) 2519 mDevicesSFMenu->exec (aEvent->globalPos()); 2520 } 2521 else if (aInd == mMouseLed) 2522 { 2523 mVmDisMouseIntegrMenu->exec (aEvent->globalPos()); 2524 } 2525 #if 0 /* TODO: Allow to setup status-bar! */ 2526 else if (aInd == mVrdpLed) 2527 { 2528 mDevicesVRDPMenu->exec (aEvent->globalPos()); 2529 } 2530 else if (aInd == mAutoresizeLed) 2531 { 2532 mVmAutoresizeMenu->exec (aEvent->globalPos()); 2533 } 2534 #endif 2535 } 2536 2537 void VBoxConsoleWnd::updateDeviceLights() 2538 { 2539 if (mConsole) 2540 { 2541 CConsole &console = mConsole->console(); 2542 int st; 2543 if (mHDLed->state() != KDeviceActivity_Null) 2544 { 2545 st = console.GetDeviceActivity (KDeviceType_HardDisk); 2546 if (mHDLed->state() != st) 2547 mHDLed->setState (st); 2548 } 2549 if (mCDLed->state() != KDeviceActivity_Null) 2550 { 2551 st = console.GetDeviceActivity (KDeviceType_DVD); 2552 if (mCDLed->state() != st) 2553 mCDLed->setState (st); 2554 } 2555 #if 0 /* TODO: Allow to setup status-bar! */ 2556 if (mFDLed->state() != KDeviceActivity_Null) 2557 { 2558 st = console.GetDeviceActivity (KDeviceType_Floppy); 2559 if (mFDLed->state() != st) 2560 mFDLed->setState (st); 2561 } 2562 #endif 2563 if (mNetLed->state() != KDeviceActivity_Null) 2564 { 2565 st = console.GetDeviceActivity (KDeviceType_Network); 2566 if (mNetLed->state() != st) 2567 mNetLed->setState (st); 2568 } 2569 if (mUSBLed->state() != KDeviceActivity_Null) 2570 { 2571 st = console.GetDeviceActivity (KDeviceType_USB); 2572 if (mUSBLed->state() != st) 2573 mUSBLed->setState (st); 2574 } 2575 if (mSFLed->state() != KDeviceActivity_Null) 2576 { 2577 st = console.GetDeviceActivity (KDeviceType_SharedFolder); 2578 if (mSFLed->state() != st) 2579 mSFLed->setState (st); 2580 } 2581 } 2582 } 2583 2584 void VBoxConsoleWnd::updateMachineState (KMachineState aState) 2585 { 2586 bool guruMeditation = false; 2587 2588 if (mConsole && mMachineState != aState) 2589 { 2590 switch (aState) 2591 { 2592 case KMachineState_Stuck: 2593 { 2594 guruMeditation = true; 2595 break; 2596 } 2597 case KMachineState_Paused: 2598 { 2599 if (!mVmPauseAction->isChecked()) 2600 mVmPauseAction->setChecked (true); 2601 break; 2602 } 2603 case KMachineState_Running: 2604 case KMachineState_Teleporting: /** @todo Live Migration: Check out this. */ 2605 case KMachineState_LiveSnapshotting: 2606 { 2607 if ( ( mMachineState == KMachineState_Paused 2608 || mMachineState == KMachineState_TeleportingPausedVM) 2609 && mVmPauseAction->isChecked() 2610 ) 2611 mVmPauseAction->setChecked (false); 2612 break; 2613 } 2614 #ifdef Q_WS_X11 2615 case KMachineState_Starting: 2616 case KMachineState_Restoring: 2617 case KMachineState_TeleportingIn: 2618 { 2619 /* The keyboard handler may wish to do some release logging 2620 on startup. Tell it that the logger is now active. */ 2621 doXKeyboardLogging (QX11Info::display()); 2622 break; 2623 } 2624 #endif 2625 default: 2626 break; 2627 } 2628 2629 bool isRunningOrPaused = aState == KMachineState_Running 2630 || aState == KMachineState_Teleporting 2631 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2632 || aState == KMachineState_Paused; 2633 2634 /* Enable/Disable actions that are not managed by updateAppearanceOf() */ 2635 2636 mRunningActions->setEnabled ( aState == KMachineState_Running 2637 || aState == KMachineState_Teleporting 2638 || aState == KMachineState_LiveSnapshotting /** @todo Live Migration: Check out this. */ 2639 ); 2640 mRunningOrPausedActions->setEnabled (isRunningOrPaused); 2641 2642 mMachineState = aState; 2643 2644 updateAppearanceOf (Caption | 2645 HardDiskStuff | DVDStuff | FloppyStuff | 2646 NetworkStuff | USBStuff | VRDPStuff | 2647 PauseAction | DisableMouseIntegrAction); 2648 2649 if ( aState == KMachineState_PoweredOff 2650 || aState == KMachineState_Saved 2651 || aState == KMachineState_Teleported 2652 || aState == KMachineState_Aborted 2653 ) 2654 { 2655 /* VM has been powered off or saved or aborted, no matter 2656 * internally or externally -- we must *safely* close the console 2657 * window unless auto closure is disabled. */ 2658 if (!mNoAutoClose) 2659 tryClose(); 2660 } 2661 } 2662 2663 if (guruMeditation) 2664 { 2665 mConsole->setIgnoreGuestResize (true); 2666 2667 CConsole console = mConsole->console(); 2668 QString logFolder = console.GetMachine().GetLogFolder(); 2669 2670 /* Take the screenshot for debugging purposes and save it */ 2671 QString fname = logFolder + "/VBox.png"; 2672 2673 CDisplay dsp = console.GetDisplay(); 2674 QImage shot = QImage (dsp.GetWidth(), dsp.GetHeight(), QImage::Format_RGB32); 2675 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 2676 shot.save (QFile::encodeName (fname), "PNG"); 2677 2678 if (vboxProblem().remindAboutGuruMeditation (console, QDir::toNativeSeparators (logFolder))) 2679 { 2680 qApp->processEvents(); 2681 console.PowerDown(); 2682 if (!console.isOk()) 2683 vboxProblem().cannotStopMachine (console); 2684 } 2685 } 2686 2687 #ifdef Q_WS_MAC 2688 if (mConsole) 2689 mConsole->updateDockOverlay(); 2690 #endif 2691 } 2692 2693 void VBoxConsoleWnd::updateMouseState (int aState) 2694 { 2695 mVmDisableMouseIntegrAction->setEnabled (aState & VBoxConsoleView::MouseAbsolute); 2696 2697 if ((aState & VBoxConsoleView::MouseAbsoluteDisabled) && 2698 (aState & VBoxConsoleView::MouseAbsolute) && 2699 !(aState & VBoxConsoleView::MouseCaptured)) 2700 { 2701 mMouseLed->setState (4); 2702 } 2703 else 2704 { 2705 mMouseLed->setState (aState & (VBoxConsoleView::MouseAbsolute | VBoxConsoleView::MouseCaptured)); 2706 } 2707 } 2708 2709 void VBoxConsoleWnd::updateAdditionsState (const QString &aVersion, 2710 bool aActive, 2711 bool aSeamlessSupported, 2712 bool aGraphicsSupported) 2713 { 2714 mVmAutoresizeGuestAction->setEnabled (aActive && aGraphicsSupported); 2715 if ((mIsSeamlessSupported != aSeamlessSupported) || 2716 (mIsGraphicsSupported != aGraphicsSupported)) 2717 { 2718 mVmSeamlessAction->setEnabled (aSeamlessSupported && aGraphicsSupported); 2719 mIsSeamlessSupported = aSeamlessSupported; 2720 mIsGraphicsSupported = aGraphicsSupported; 2721 /* If seamless mode should be enabled then check if it is enabled 2722 * currently and re-enable it if open-view procedure is finished */ 2723 if (mVmSeamlessAction->isChecked() && mIsOpenViewFinished && aSeamlessSupported && aGraphicsSupported) 2724 toggleFullscreenMode (true, true); 2725 /* Disable auto-resizing if advanced graphics are not available */ 2726 mConsole->setAutoresizeGuest (mIsGraphicsSupported && mVmAutoresizeGuestAction->isChecked()); 2727 mVmAutoresizeGuestAction->setEnabled (mIsGraphicsSupported); 2728 } 2729 2730 /* Check the GA version only in case of additions are active */ 2731 if (!aActive) 2732 return; 2733 2734 /* Check the Guest Additions version and warn the user about possible 2735 * compatibility issues in case if the installed version is outdated. */ 2736 uint version = aVersion.toUInt(); 2737 QString versionStr = QString ("%1.%2") 2738 .arg (RT_HIWORD (version)).arg (RT_LOWORD (version)); 2739 QString expectedStr = QString ("%1.%2") 2740 .arg (VMMDEV_VERSION_MAJOR).arg (VMMDEV_VERSION_MINOR); /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/ 2741 2742 if (RT_HIWORD (version) < VMMDEV_VERSION_MAJOR) 2743 { 2744 vboxProblem().warnAboutTooOldAdditions (this, versionStr, expectedStr); 2745 } 2746 else if (RT_HIWORD (version) == VMMDEV_VERSION_MAJOR && 2747 RT_LOWORD (version) < VMMDEV_VERSION_MINOR) 2748 { 2749 vboxProblem().warnAboutOldAdditions (this, versionStr, expectedStr); 2750 } 2751 else if (version > VMMDEV_VERSION) 2752 { 2753 vboxProblem().warnAboutNewAdditions (this, versionStr, expectedStr); 2754 } 2755 } 2756 2757 void VBoxConsoleWnd::updateNetworkAdaptersState() 2758 { 2759 updateAppearanceOf (NetworkStuff); 2760 } 2761 2762 void VBoxConsoleWnd::updateUsbState() 2763 { 2764 updateAppearanceOf (USBStuff); 2765 } 2766 2767 void VBoxConsoleWnd::updateMediaDriveState (VBoxDefs::MediumType aType) 2768 { 2769 Assert (aType == VBoxDefs::MediumType_DVD || aType == VBoxDefs::MediumType_Floppy); 2770 updateAppearanceOf (aType == VBoxDefs::MediumType_DVD ? DVDStuff : 2771 aType == VBoxDefs::MediumType_Floppy ? FloppyStuff : 2772 AllStuff); 2773 } 2774 2775 void VBoxConsoleWnd::updateSharedFoldersState() 2776 { 2777 updateAppearanceOf (SharedFolderStuff); 2778 } 2779 2780 /** 2781 * This slot is called just after leaving the fullscreen/seamless mode, 2782 * when the console was resized to previous size. 2783 */ 2784 void VBoxConsoleWnd::onExitFullscreen() 2785 { 2786 mConsole->setIgnoreMainwndResize (false); 2787 } 2788 2789 void VBoxConsoleWnd::unlockActionsSwitch() 2790 { 2791 if (mIsSeamless) 2792 mVmSeamlessAction->setEnabled (true); 2793 else if (mIsFullscreen) 2794 mVmFullscreenAction->setEnabled (true); 2795 else 2796 { 2797 mVmSeamlessAction->setEnabled (mIsSeamlessSupported && mIsGraphicsSupported); 2798 mVmFullscreenAction->setEnabled (true); 2799 } 2800 2801 #ifdef Q_WS_MAC 2802 if (!mIsSeamless) 2803 { 2804 /* Fade back to the normal gamma */ 2805 CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); 2806 CGReleaseDisplayFadeReservation (mFadeToken); 2807 } 2808 mConsole->setMouseCoalescingEnabled (true); 2809 #endif 2810 2811 #ifdef Q_WS_X11 2812 if (vboxGlobal().isKWinManaged() && !mIsSeamless && !mIsFullscreen) 2813 { 2814 /* Workaround for a KWin bug to let console window to exit 2815 * seamless mode correctly. */ 2816 setWindowFlags(Qt::Window); 2817 setVisible(true); 2818 } 2819 #endif 2820 } 2821 2822 void VBoxConsoleWnd::mtExitMode() 2823 { 2824 if (mIsSeamless) 2825 mVmSeamlessAction->toggle(); 2826 else 2827 mVmFullscreenAction->toggle(); 2828 } 2829 2830 void VBoxConsoleWnd::mtCloseVM() 2831 { 2832 mVmCloseAction->trigger(); 2833 } 2834 2835 void VBoxConsoleWnd::mtMaskUpdate() 2836 { 2837 if (mIsSeamless) 2838 setMask (mConsole->lastVisibleRegion()); 2839 } 2840 2841 void VBoxConsoleWnd::changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent) 2842 { 2843 #ifdef Q_WS_MAC 2844 if (mConsole) 2845 { 2846 mConsole->setDockIconEnabled (aEvent.mChanged); 2847 mConsole->updateDockOverlay(); 2848 } 2849 #else 2850 Q_UNUSED (aEvent); 2851 #endif 2852 } 2853 2854 void VBoxConsoleWnd::changePresentationMode (const VBoxChangePresentationModeEvent &aEvent) 2855 { 2856 Q_UNUSED (aEvent); 2857 #ifdef Q_WS_MAC 2858 # ifdef QT_MAC_USE_COCOA 2859 if (mIsFullscreen) 2860 { 2861 /* First check if we are on the primary screen, only than the 2862 presentation mode have to be changed. */ 2863 QDesktopWidget* pDesktop = QApplication::desktop(); 2864 if (pDesktop->screenNumber(this) == pDesktop->primaryScreen()) 2865 { 2866 QString testStr = vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_PresentationModeEnabled).toLower(); 2867 /* Default to false if it is an empty value */ 2868 if (testStr.isEmpty() || testStr == "false") 2869 SetSystemUIMode (kUIModeAllHidden, 0); 2870 else 2871 SetSystemUIMode (kUIModeAllSuppressed, 0); 2872 } 2873 } 2874 else 2875 SetSystemUIMode (kUIModeNormal, 0); 2876 # endif /* QT_MAC_USE_COCOA */ 2877 #endif 2878 } 2879 2880 /** 2881 * Called (on non-UI thread!) when a global GUI setting changes. 2882 */ 2883 void VBoxConsoleWnd::processGlobalSettingChange (const char * /* aPublicName */, const char * /* aName */) 2884 { 2885 mHostkeyName->setText (QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())); 2886 } 2887 2888 /** 2889 * This function checks the status of required features and 2890 * makes a warning and/or some action if something necessary 2891 * is not in good condition. 2892 * Does nothing if no console view was opened. 2893 */ 2894 void VBoxConsoleWnd::checkRequiredFeatures() 2895 { 2896 if (!mConsole) return; 2897 2898 CConsole console = mConsole->console(); 2899 2900 /* Check if the virtualization feature is required. */ 2901 bool is64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType ( 2902 console.GetGuest().GetOSTypeId()).GetIs64Bit(); 2903 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType ( 2904 console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx(); 2905 Assert(!is64BitsGuest || fRecommendVirtEx); 2906 bool isVirtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 2907 if (fRecommendVirtEx && !isVirtEnabled) 2908 { 2909 bool ret; 2910 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost() 2911 .GetProcessorFeature (KProcessorFeature_HWVirtEx); 2912 2913 vmPause (true); 2914 2915 if (is64BitsGuest) 2916 ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported); 743 { 744 /* Normalize to the optimal size */ 745 machineView()->normalizeGeometry(true /* adjust position? */); 746 747 /* Move newly created window to the screen center: */ 748 m_normalGeometry = geometry(); 749 m_normalGeometry.moveCenter(ar.center()); 750 setGeometry(m_normalGeometry); 751 } 752 } 753 754 /* Availability settings */ 755 { 756 /* USB Stuff: */ 757 CUSBController usbController = machine.GetUSBController(); 758 if (usbController.isNull()) 759 { 760 /* Hide USB Menu: */ 761 indicatorsPool()->indicator(UIIndicatorIndex_USBDevices)->setHidden(true); 762 } 2917 763 else 2918 ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported); 2919 2920 if (ret == true) 2921 close(); 2922 else 2923 vmPause (false); 2924 } 2925 } 2926 2927 void VBoxConsoleWnd::activateUICustomizations() 2928 { 2929 VBoxGlobalSettings settings = vboxGlobal().settings(); 2930 /* Process known keys */ 2931 menuBar()->setHidden (settings.isFeatureActive ("noMenuBar")); 2932 statusBar()->setHidden (settings.isFeatureActive ("noStatusBar")); 2933 } 2934 2935 void VBoxConsoleWnd::updateAppearanceOf (int aElement) 2936 { 2937 if (!mConsole) return; 2938 2939 CMachine machine = mSession.GetMachine(); 2940 CConsole console = mConsole->console(); 2941 2942 bool isStrictRunningOrPaused = mMachineState == KMachineState_Running 2943 || mMachineState == KMachineState_Paused; 2944 bool isRunningOrPaused = isStrictRunningOrPaused 2945 || mMachineState == KMachineState_Teleporting 2946 || mMachineState == KMachineState_LiveSnapshotting; 2947 2948 if (aElement & Caption) 2949 { 2950 QString snapshotName; 2951 if (machine.GetSnapshotCount() > 0) 2952 { 2953 CSnapshot snapshot = machine.GetCurrentSnapshot(); 2954 snapshotName = " (" + snapshot.GetName() + ")"; 2955 } 2956 setWindowTitle (machine.GetName() + snapshotName + 2957 " [" + vboxGlobal().toString (mMachineState) + "] - " + 2958 mCaptionPrefix); 2959 mMiniToolBar->setDisplayText (machine.GetName() + snapshotName); 2960 } 2961 if (aElement & HardDiskStuff) 2962 { 2963 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2964 "of the virtual hard disks:</nobr>%1</p>", "HDD tooltip"); 2965 QString data; 2966 bool attachmentsPresent = false; 2967 2968 CStorageControllerVector controllers = machine.GetStorageControllers(); 2969 foreach (const CStorageController &controller, controllers) 2970 { 2971 QString attData; 2972 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 2973 foreach (const CMediumAttachment &attachment, attachments) 2974 { 2975 if (attachment.GetType() != KDeviceType_HardDisk) 2976 continue; 2977 attData += QString ("<br> <nobr>%1: %2</nobr>") 2978 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 2979 .arg (VBoxMedium (attachment.GetMedium(), VBoxDefs::MediumType_HardDisk).location()); 2980 attachmentsPresent = true; 2981 } 2982 if (!attData.isNull()) 2983 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 2984 } 2985 2986 if (!attachmentsPresent) 2987 data += tr ("<br><nobr><b>No hard disks attached</b></nobr>", "HDD tooltip"); 2988 2989 mHDLed->setToolTip (tip.arg (data)); 2990 mHDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 2991 } 2992 if (aElement & DVDStuff) 2993 { 2994 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 2995 "of the CD/DVD devices:</nobr>%1</p>", "CD/DVD tooltip"); 2996 QString data; 2997 bool attachmentsPresent = false; 2998 2999 CStorageControllerVector controllers = machine.GetStorageControllers(); 3000 foreach (const CStorageController &controller, controllers) 3001 { 3002 QString attData; 3003 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3004 foreach (const CMediumAttachment &attachment, attachments) 3005 { 3006 if (attachment.GetType() != KDeviceType_DVD) 3007 continue; 3008 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_DVD); 3009 attData += QString ("<br> <nobr>%1: %2</nobr>") 3010 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3011 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3012 if (!vboxMedium.isNull()) 3013 attachmentsPresent = true; 3014 } 3015 if (!attData.isNull()) 3016 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3017 } 3018 3019 if (data.isNull()) 3020 data = tr ("<br><nobr><b>No CD/DVD devices attached</b></nobr>", "CD/DVD tooltip"); 3021 3022 mCDLed->setToolTip (tip.arg (data)); 3023 mCDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3024 } 3025 #if 0 /* TODO: Allow to setup status-bar! */ 3026 if (aElement & FloppyStuff) 3027 { 3028 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity " 3029 "of the floppy devices:</nobr>%1</p>", "FD tooltip"); 3030 QString data; 3031 bool attachmentsPresent = false; 3032 3033 CStorageControllerVector controllers = machine.GetStorageControllers(); 3034 foreach (const CStorageController &controller, controllers) 3035 { 3036 QString attData; 3037 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController (controller.GetName()); 3038 foreach (const CMediumAttachment &attachment, attachments) 3039 { 3040 if (attachment.GetType() != KDeviceType_Floppy) 3041 continue; 3042 VBoxMedium vboxMedium (attachment.GetMedium(), VBoxDefs::MediumType_Floppy); 3043 attData += QString ("<br> <nobr>%1: %2</nobr>") 3044 .arg (vboxGlobal().toString (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice()))) 3045 .arg (vboxMedium.isNull() || vboxMedium.isHostDrive() ? vboxMedium.name() : vboxMedium.location()); 3046 if (!vboxMedium.isNull()) 3047 attachmentsPresent = true; 3048 } 3049 if (!attData.isNull()) 3050 data += QString ("<br><nobr><b>%1</b></nobr>").arg (controller.GetName()) + attData; 3051 } 3052 3053 if (data.isNull()) 3054 data = tr ("<br><nobr><b>No floppy devices attached</b></nobr>", "FD tooltip"); 3055 3056 mFDLed->setToolTip (tip.arg (data)); 3057 mFDLed->setState (attachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null); 3058 } 3059 #endif 3060 if (aElement & NetworkStuff) 3061 { 3062 ulong maxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount(); 3063 ulong count = 0; 3064 for (ulong slot = 0; slot < maxCount; ++ slot) 3065 if (machine.GetNetworkAdapter (slot).GetEnabled()) 3066 ++ count; 3067 mNetLed->setState (count > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null); 3068 3069 mDevicesNetworkDialogAction->setEnabled (isStrictRunningOrPaused && count > 0); 3070 mDevicesNetworkMenu->setEnabled (isStrictRunningOrPaused && count > 0); 3071 3072 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of the " 3073 "network interfaces:</nobr>%1</p>", "Network adapters tooltip"); 3074 QString info; 3075 3076 for (ulong slot = 0; slot < maxCount; ++ slot) 3077 { 3078 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot); 3079 if (adapter.GetEnabled()) 3080 info += tr ("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip") 3081 .arg (slot + 1) 3082 .arg (vboxGlobal().toString (adapter.GetAttachmentType())) 3083 .arg (adapter.GetCableConnected() ? 3084 tr ("connected", "Network adapters tooltip") : 3085 tr ("disconnected", "Network adapters tooltip")); 3086 } 3087 3088 if (info.isNull()) 3089 info = tr ("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip"); 3090 3091 mNetLed->setToolTip (tip.arg (info)); 3092 } 3093 if (aElement & USBStuff) 3094 { 3095 if (!mUSBLed->isHidden()) 3096 { 3097 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3098 "the attached USB devices:</nobr>%1</p>", "USB device tooltip"); 3099 QString info; 3100 3101 CUSBController usbctl = machine.GetUSBController(); 3102 if (!usbctl.isNull() && usbctl.GetEnabled()) 3103 { 3104 mDevicesUSBMenu->setEnabled (isStrictRunningOrPaused); 3105 3106 CUSBDeviceVector devsvec = console.GetUSBDevices(); 3107 for (int i = 0; i < devsvec.size(); ++ i) 3108 { 3109 CUSBDevice usb = devsvec [i]; 3110 info += QString ("<br><b><nobr>%1</nobr></b>").arg (vboxGlobal().details (usb)); 3111 } 3112 if (info.isNull()) 3113 info = tr ("<br><nobr><b>No USB devices attached</b></nobr>", "USB device tooltip"); 3114 } 3115 else 3116 { 3117 mDevicesUSBMenu->setEnabled (false); 3118 info = tr ("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip"); 3119 } 3120 3121 mUSBLed->setToolTip (tip.arg (info)); 3122 } 3123 } 3124 if (aElement & VRDPStuff) 3125 { 3126 CVRDPServer vrdpsrv = mSession.GetMachine().GetVRDPServer(); 3127 if (!vrdpsrv.isNull()) 3128 { 3129 /* update menu&status icon state */ 3130 bool isVRDPEnabled = vrdpsrv.GetEnabled(); 3131 mDevicesSwitchVrdpAction->setChecked (isVRDPEnabled); 3132 #if 0 /* TODO: Allow to setup status-bar! */ 3133 mVrdpLed->setState (isVRDPEnabled ? 1 : 0); 3134 3135 QString tip = tr ("Indicates whether the Remote Display (VRDP Server) " 3136 "is enabled (<img src=:/vrdp_16px.png/>) or not " 3137 "(<img src=:/vrdp_disabled_16px.png/>)."); 3138 if (vrdpsrv.GetEnabled()) 3139 tip += tr ("<hr>The VRDP Server is listening on port %1").arg (vrdpsrv.GetPort()); 3140 mVrdpLed->setToolTip (tip); 3141 #endif 3142 } 3143 } 3144 if (aElement & SharedFolderStuff) 3145 { 3146 QString tip = tr ("<p style='white-space:pre'><nobr>Indicates the activity of " 3147 "the machine's shared folders:</nobr>%1</p>", "Shared folders tooltip"); 3148 3149 QString data; 3150 QMap <QString, QString> sfs; 3151 3152 mDevicesSFMenu->setEnabled (true); 3153 3154 /* Permanent folders */ 3155 CSharedFolderVector psfvec = machine.GetSharedFolders(); 3156 3157 for (int i = 0; i < psfvec.size(); ++ i) 3158 { 3159 CSharedFolder sf = psfvec [i]; 3160 sfs.insert (sf.GetName(), sf.GetHostPath()); 3161 } 3162 3163 /* Transient folders */ 3164 CSharedFolderVector tsfvec = console.GetSharedFolders(); 3165 3166 for (int i = 0; i < tsfvec.size(); ++ i) 3167 { 3168 CSharedFolder sf = tsfvec[i]; 3169 sfs.insert (sf.GetName(), sf.GetHostPath()); 3170 } 3171 3172 for (QMap <QString, QString>::const_iterator it = sfs.constBegin(); it != sfs.constEnd(); ++ it) 3173 { 3174 /* Select slashes depending on the OS type */ 3175 if (VBoxGlobal::isDOSType (console.GetGuest().GetOSTypeId())) 3176 data += QString ("<br><nobr><b>\\\\vboxsvr\\%1 </b></nobr><nobr>%2</nobr>") 3177 .arg (it.key(), it.value()); 3178 else 3179 data += QString ("<br><nobr><b>%1 </b></nobr><nobr>%2</nobr>") 3180 .arg (it.key(), it.value()); 3181 } 3182 3183 if (sfs.count() == 0) 3184 data = tr ("<br><nobr><b>No shared folders</b></nobr>", "Shared folders tooltip"); 3185 3186 mSFLed->setToolTip (tip.arg (data)); 3187 } 3188 if (aElement & VirtualizationStuff) 3189 { 3190 bool virtEnabled = console.GetDebugger().GetHWVirtExEnabled(); 3191 QString virtualization = virtEnabled ? 3192 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") : 3193 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)"); 3194 3195 bool nestEnabled = console.GetDebugger().GetHWVirtExNestedPagingEnabled(); 3196 QString nestedPaging = nestEnabled ? 3197 VBoxVMInformationDlg::tr ("Enabled", "nested paging") : 3198 VBoxVMInformationDlg::tr ("Disabled", "nested paging"); 3199 3200 QString tip (tr ("Indicates the status of the hardware virtualization " 3201 "features used by this virtual machine:" 3202 "<br><nobr><b>%1:</b> %2</nobr>" 3203 "<br><nobr><b>%3:</b> %4</nobr>", 3204 "Virtualization Stuff LED") 3205 .arg (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization) 3206 .arg (VBoxVMInformationDlg::tr ("Nested Paging"), nestedPaging)); 3207 3208 int cpuCount = console.GetMachine().GetCPUCount(); 3209 if (cpuCount > 1) 3210 tip += tr ("<br><nobr><b>%1:</b> %2</nobr>", "Virtualization Stuff LED") 3211 .arg (VBoxGlobal::tr ("Processor(s)", "details report")).arg (cpuCount); 3212 3213 mVirtLed->setToolTip (tip); 3214 mVirtLed->setState (virtEnabled); 3215 } 3216 if (aElement & PauseAction) 3217 { 3218 if (!mVmPauseAction->isChecked()) 3219 { 3220 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("&Pause"), "P")); 3221 mVmPauseAction->setStatusTip (tr ("Suspend the execution of the virtual machine")); 3222 } 3223 else 3224 { 3225 mVmPauseAction->setText (VBoxGlobal::insertKeyToActionText (tr ("R&esume"), "P")); 3226 mVmPauseAction->setStatusTip (tr ("Resume the execution of the virtual machine" ) ); 3227 } 3228 mVmPauseAction->setEnabled (isRunningOrPaused); 3229 } 3230 if (aElement & DisableMouseIntegrAction) 3231 { 3232 if (!mVmDisableMouseIntegrAction->isChecked()) 3233 { 3234 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Disable &Mouse Integration"), "I")); 3235 mVmDisableMouseIntegrAction->setStatusTip (tr ("Temporarily disable host mouse pointer integration")); 3236 } 3237 else 3238 { 3239 mVmDisableMouseIntegrAction->setText (VBoxGlobal::insertKeyToActionText (tr ("Enable &Mouse Integration"), "I")); 3240 mVmDisableMouseIntegrAction->setStatusTip (tr ("Enable temporarily disabled host mouse pointer integration")); 3241 } 3242 if ( mMachineState == KMachineState_Running 3243 || mMachineState == KMachineState_Teleporting 3244 || mMachineState == KMachineState_LiveSnapshotting 3245 ) 3246 mVmDisableMouseIntegrAction->setEnabled (mConsole->isMouseAbsolute()); 3247 else 3248 mVmDisableMouseIntegrAction->setEnabled (false); 3249 } 3250 } 3251 3252 /** 3253 * @return @c true if successfully performed the requested operation and false 3254 * otherwise. 3255 */ 3256 bool VBoxConsoleWnd::toggleFullscreenMode (bool aOn, bool aSeamless) 3257 { 3258 /* Please note: For some platforms like the Mac, the calling order of the 3259 * functions in this methods is vital. So please be careful on changing 3260 * this. */ 3261 3262 QSize initialSize = size(); 3263 if (aSeamless || mConsole->isAutoresizeGuestActive()) 3264 { 3265 QRect screen = aSeamless ? 3266 QApplication::desktop()->availableGeometry (this) : 3267 QApplication::desktop()->screenGeometry (this); 3268 ULONG64 availBits = mSession.GetMachine().GetVRAMSize() /* vram */ 3269 * _1M /* mb to bytes */ 3270 * 8; /* to bits */ 3271 ULONG guestBpp = mConsole->console().GetDisplay().GetBitsPerPixel(); 3272 ULONG64 usedBits = (screen.width() /* display width */ 3273 * screen.height() /* display height */ 3274 * guestBpp 3275 + _1M * 8) /* current cache per screen - may be changed in future */ 3276 * mSession.GetMachine().GetMonitorCount() /**< @todo fix assumption that all screens have same resolution */ 3277 + 4096 * 8; /* adapter info */ 3278 if (aOn && (availBits < usedBits)) 3279 { 3280 if (aSeamless) 3281 { 3282 vboxProblem().cannotEnterSeamlessMode ( 3283 screen.width(), screen.height(), guestBpp, 3284 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3285 return false; 3286 } 3287 else 3288 { 3289 int result = vboxProblem().cannotEnterFullscreenMode ( 3290 screen.width(), screen.height(), guestBpp, 3291 (((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M); 3292 if (result == QIMessageBox::Cancel) 3293 return false; 3294 } 3295 } 3296 } 3297 3298 AssertReturn (mConsole, false); 3299 AssertReturn ((mHiddenChildren.empty() == aOn), false); 3300 AssertReturn ((aSeamless && mIsSeamless != aOn) || 3301 (!aSeamless && mIsFullscreen != aOn), false); 3302 if (aOn) 3303 AssertReturn ((aSeamless && !mIsFullscreen) || 3304 (!aSeamless && !mIsSeamless), false); 3305 3306 if (aOn) 3307 { 3308 /* Take the toggle hot key from the menu item. Since 3309 * VBoxGlobal::extractKeyFromActionText gets exactly the 3310 * linked key without the 'Host+' part we are adding it here. */ 3311 QString hotKey = QString ("Host+%1") 3312 .arg (VBoxGlobal::extractKeyFromActionText (aSeamless ? 3313 mVmSeamlessAction->text() : mVmFullscreenAction->text())); 3314 3315 Assert (!hotKey.isEmpty()); 3316 3317 /* Show the info message. */ 3318 bool ok = aSeamless ? 3319 vboxProblem().confirmGoingSeamless (hotKey) : 3320 vboxProblem().confirmGoingFullscreen (hotKey); 3321 if (!ok) 3322 return false; 3323 } 3324 3325 #ifdef Q_WS_MAC 3326 if (!aSeamless) 3327 { 3328 /* Fade to black */ 3329 CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &mFadeToken); 3330 CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); 3331 } 3332 #endif 3333 3334 if (aSeamless) 3335 { 3336 /* Activate the auto-resize feature required for the seamless mode. */ 3337 if (!mVmAutoresizeGuestAction->isChecked()) 3338 mVmAutoresizeGuestAction->setChecked (true); 3339 3340 /* Activate the mouse integration feature for the seamless mode. */ 3341 if (mVmDisableMouseIntegrAction->isChecked()) 3342 mVmDisableMouseIntegrAction->setChecked (false); 3343 3344 mVmAdjustWindowAction->setEnabled (!aOn); 3345 mVmFullscreenAction->setEnabled (!aOn); 3346 mVmAutoresizeGuestAction->setEnabled (!aOn); 3347 mVmDisableMouseIntegrAction->setEnabled (!aOn); 3348 3349 mConsole->console().GetDisplay().SetSeamlessMode (aOn); 3350 mIsSeamless = aOn; 3351 } 3352 else 3353 { 3354 mIsFullscreen = aOn; 3355 mVmAdjustWindowAction->setEnabled (!aOn); 3356 mVmSeamlessAction->setEnabled (!aOn && mIsSeamlessSupported && mIsGraphicsSupported); 3357 } 3358 3359 bool wasHidden = isHidden(); 3360 3361 /* Temporarily disable the mode-related action to make sure 3362 * user can not leave the mode before he enter it and inside out. */ 3363 aSeamless ? mVmSeamlessAction->setEnabled (false) : 3364 mVmFullscreenAction->setEnabled (false); 3365 3366 /* Calculate initial console size */ 3367 QSize consoleSize; 3368 3369 if (aOn) 3370 { 3371 consoleSize = mConsole->frameSize(); 3372 consoleSize -= QSize (mConsole->frameWidth() * 2, mConsole->frameWidth() * 2); 3373 3374 /* Toggle console to manual resize mode. */ 3375 mConsole->setIgnoreMainwndResize (true); 3376 3377 /* Memorize the maximized state. */ 3378 QDesktopWidget *dtw = QApplication::desktop(); 3379 mWasMax = isWindowMaximized() && 3380 dtw->availableGeometry().width() == frameSize().width() && 3381 dtw->availableGeometry().height() == frameSize().height(); 3382 3383 /* Save the previous scroll-view minimum size before entering 3384 * fullscreen/seamless state to restore this minimum size before 3385 * the exiting fullscreen. Required for correct scroll-view and 3386 * guest display update in SDL mode. */ 3387 mPrevMinSize = mConsole->minimumSize(); 3388 mConsole->setMinimumSize (0, 0); 3389 3390 /* let the widget take the whole available desktop space */ 3391 QRect scrGeo = aSeamless ? 3392 dtw->availableGeometry (this) : dtw->screenGeometry (this); 3393 3394 /* It isn't guaranteed that the guest os set the video mode that 3395 * we requested. So after all the resizing stuff set the clipping 3396 * mask and the spacing shifter to the corresponding values. */ 3397 if (aSeamless) 3398 setViewInSeamlessMode (scrGeo); 3399 3400 #ifdef Q_WS_WIN 3401 mPrevRegion = dtw->screenGeometry (this); 3402 #endif 3403 3404 /* Hide all but the central widget containing the console view. */ 3405 QList <QWidget*> list (findChildren <QWidget*> ()); 3406 QList <QWidget*> excludes; 3407 excludes << centralWidget() << centralWidget()->findChildren <QWidget*> (); 3408 foreach (QWidget *w, list) 3409 { 3410 if (!excludes.contains (w)) 3411 { 3412 if (!w->isHidden()) 3413 { 3414 w->hide(); 3415 mHiddenChildren.append (w); 3416 } 3417 } 3418 } 3419 3420 /* Adjust colors and appearance. */ 3421 mErasePalette = centralWidget()->palette(); 3422 QPalette palette(mErasePalette); 3423 palette.setColor (centralWidget()->backgroundRole(), Qt::black); 3424 centralWidget()->setPalette (palette); 3425 centralWidget()->setAutoFillBackground (!aSeamless); 3426 mConsoleStyle = mConsole->frameStyle(); 3427 mConsole->setFrameStyle (QFrame::NoFrame); 3428 mConsole->setMaximumSize (scrGeo.size()); 3429 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3430 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff); 3431 } 3432 else 3433 { 3434 /* Reset the shifting spacers. */ 3435 mShiftingSpacerLeft->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3436 mShiftingSpacerTop->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3437 mShiftingSpacerRight->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3438 mShiftingSpacerBottom->changeSize (0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); 3439 3440 /* Restore the previous scroll-view minimum size before the exiting 3441 * fullscreen. Required for correct scroll-view and guest display 3442 * update in SDL mode. */ 3443 mConsole->setMinimumSize (mPrevMinSize); 3444 3445 #ifdef Q_WS_MAC 3446 if (aSeamless) 3447 { 3448 /* Please note: All the stuff below has to be done before the 3449 * window switch back to normal size. Qt changes the winId on the 3450 * fullscreen switch and make this stuff useless with the old 3451 * winId. So please be careful on rearrangement of the method 3452 * calls. */ 3453 /* Undo all mac specific installations */ 3454 ::darwinSetShowsWindowTransparent (this, false); 3455 } 3456 #endif 3457 3458 /* Adjust colors and appearance. */ 3459 clearMask(); 3460 centralWidget()->setPalette (mErasePalette); 3461 centralWidget()->setAutoFillBackground (false); 3462 mConsole->setFrameStyle (mConsoleStyle); 3463 mConsole->setMaximumSize (mConsole->sizeHint()); 3464 mConsole->setHorizontalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3465 mConsole->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded); 3466 3467 /* Show everything hidden when going fullscreen. */ 3468 foreach (QPointer <QWidget> child, mHiddenChildren) 3469 if (child) child->show(); 3470 mHiddenChildren.clear(); 3471 } 3472 3473 /* Set flag for waiting host resize if it awaited during mode entering */ 3474 if ((mIsFullscreen || mIsSeamless) && (consoleSize != initialSize)) 3475 mIsWaitingModeResize = true; 3476 3477 if (!aOn) 3478 { 3479 /* Animation takes a bit long, the mini toolbar is still disappearing 3480 * when switched to normal mode so hide it completely */ 3481 mMiniToolBar->hide(); 3482 mMiniToolBar->updateDisplay (false, true); 3483 } 3484 3485 /* Toggle qt full-screen mode */ 3486 switchToFullscreen (aOn, aSeamless); 3487 3488 if (aOn) 3489 { 3490 mMiniToolBar->setSeamlessMode (aSeamless); 3491 mMiniToolBar->updateDisplay (true, true); 3492 } 3493 3494 #ifdef Q_WS_MAC 3495 if (aOn && aSeamless) 3496 { 3497 /* Please note: All the stuff below has to be done after the window has 3498 * switched to fullscreen. Qt changes the winId on the fullscreen 3499 * switch and make this stuff useless with the old winId. So please be 3500 * careful on rearrangement of the method calls. */ 3501 ::darwinSetShowsWindowTransparent (this, true); 3502 } 3503 #endif 3504 3505 /* Send guest size hint */ 3506 mConsole->toggleFSMode (consoleSize); 3507 3508 /* Process all console attributes changes and sub-widget hidings */ 3509 qApp->processEvents(); 3510 3511 if (!mIsWaitingModeResize) 3512 onExitFullscreen(); 3513 3514 /* Unlock FS actions locked during modes toggling */ 3515 QTimer::singleShot (300, this, SLOT (unlockActionsSwitch())); 3516 3517 #ifdef Q_WS_MAC /* wasHidden is wrong on the mac it seems. */ 3518 /** @todo figure out what is really wrong here... */ 3519 if (!wasHidden) 3520 show(); 3521 #else 3522 if (wasHidden) 3523 hide(); 3524 #endif 3525 3526 return true; 3527 } 3528 3529 void VBoxConsoleWnd::switchToFullscreen (bool aOn, bool aSeamless) 3530 { 3531 #ifdef Q_WS_MAC 3532 # ifndef QT_MAC_USE_COCOA 3533 /* setWindowState removes the window group connection somehow. So save it 3534 * temporary. */ 3535 WindowGroupRef g = GetWindowGroup (::darwinToNativeWindow (this)); 3536 # endif /* !QT_MAC_USE_COCOA */ 3537 if (aSeamless) 3538 if (aOn) 3539 { 3540 /* Save for later restoring */ 3541 mNormalGeometry = geometry(); 3542 mSavedFlags = windowFlags(); 3543 /* Remove the frame from the window */ 3544 const QRect fullscreen (qApp->desktop()->screenGeometry (qApp->desktop()->screenNumber (this))); 3545 setParent (0, Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); 3546 setGeometry (fullscreen); 3547 /* Set it maximized */ 3548 setWindowState (windowState() ^ Qt::WindowMaximized); 3549 } 3550 else 3551 { 3552 /* Restore old values */ 3553 setParent (0, mSavedFlags); 3554 setGeometry (mNormalGeometry); 3555 } 3556 else 3557 { 3558 /* Here we are going really fullscreen */ 3559 setWindowState (windowState() ^ Qt::WindowFullScreen); 3560 changePresentationMode (VBoxChangePresentationModeEvent(aOn)); 3561 } 3562 3563 # ifndef QT_MAC_USE_COCOA 3564 /* Reassign the correct window group. */ 3565 SetWindowGroup (::darwinToNativeWindow (this), g); 3566 # endif /* !QT_MAC_USE_COCOA */ 3567 #else 3568 NOREF (aOn); 3569 NOREF (aSeamless); 3570 setWindowState (windowState() ^ Qt::WindowFullScreen); 3571 #endif 3572 } 3573 3574 void VBoxConsoleWnd::setViewInSeamlessMode (const QRect &aTargetRect) 3575 { 3576 #ifndef Q_WS_MAC 3577 /* It isn't guaranteed that the guest os set the video mode that 3578 * we requested. So after all the resizing stuff set the clipping 3579 * mask and the spacing shifter to the corresponding values. */ 3580 QDesktopWidget *dtw = QApplication::desktop(); 3581 QRect sRect = dtw->screenGeometry (this); 3582 QRect aRect (aTargetRect); 3583 mMaskShift.scale (aTargetRect.left(), aTargetRect.top(), Qt::IgnoreAspectRatio); 3584 /* Set the clipping mask */ 3585 mStrictedRegion = aRect; 3586 /* Set the shifting spacer */ 3587 mShiftingSpacerLeft->changeSize (RT_ABS (sRect.left() - aRect.left()), 0, 3588 QSizePolicy::Fixed, QSizePolicy::Preferred); 3589 mShiftingSpacerTop->changeSize (0, RT_ABS (sRect.top() - aRect.top()), 3590 QSizePolicy::Preferred, QSizePolicy::Fixed); 3591 mShiftingSpacerRight->changeSize (RT_ABS (sRect.right() - aRect.right()), 0, 3592 QSizePolicy::Fixed, QSizePolicy::Preferred); 3593 mShiftingSpacerBottom->changeSize (0, RT_ABS (sRect.bottom() - aRect.bottom()), 3594 QSizePolicy::Preferred, QSizePolicy::Fixed); 3595 #else // !Q_WS_MAC 3596 NOREF (aTargetRect); 3597 #endif // !Q_WS_MAC 3598 } 3599 3600 /** 3601 * Closes the console view opened by openView(). 3602 * Does nothing if no console view was opened. 3603 */ 3604 void VBoxConsoleWnd::closeView() 3605 { 3606 LogFlowFuncEnter(); 3607 3608 if (!mConsole) 3609 { 3610 LogFlow (("Already closed!\n")); 3611 LogFlowFuncLeave(); 3612 return; 3613 } 3614 3615 mConsole->detach(); 3616 centralWidget()->layout()->removeWidget (mConsole); 3617 delete mConsole; 3618 mConsole = 0; 3619 mSession.Close(); 3620 mSession.detach(); 3621 3622 LogFlowFuncLeave(); 3623 } 3624 3625 #ifdef VBOX_WITH_DEBUGGER_GUI 3626 3627 /** 3628 * Prepare the Debug menu. 3629 */ 3630 void VBoxConsoleWnd::dbgPrepareDebugMenu() 3631 { 3632 /* The "Logging" item. */ 3633 bool fEnabled = false; 3634 bool fChecked = false; 3635 CConsole console = mSession.GetConsole(); 3636 if (console.isOk()) 3637 { 3638 CMachineDebugger cdebugger = console.GetDebugger(); 3639 if (console.isOk()) 3640 { 3641 fEnabled = true; 3642 fChecked = cdebugger.GetLogEnabled() != FALSE; 3643 } 3644 } 3645 if (fEnabled != mDbgLoggingAction->isEnabled()) 3646 mDbgLoggingAction->setEnabled (fEnabled); 3647 if (fChecked != mDbgLoggingAction->isChecked()) 3648 mDbgLoggingAction->setChecked (fChecked); 3649 } 3650 3651 /** 3652 * Called when the Debug->Statistics... menu item is selected. 3653 */ 3654 void VBoxConsoleWnd::dbgShowStatistics() 3655 { 3656 if (dbgCreated()) 3657 mDbgGuiVT->pfnShowStatistics (mDbgGui); 3658 } 3659 3660 /** 3661 * Called when the Debug->Command Line... menu item is selected. 3662 */ 3663 void VBoxConsoleWnd::dbgShowCommandLine() 3664 { 3665 if (dbgCreated()) 3666 mDbgGuiVT->pfnShowCommandLine (mDbgGui); 3667 } 3668 3669 /** 3670 * Called when the Debug->Logging menu item is selected. 3671 */ 3672 void VBoxConsoleWnd::dbgLoggingToggled (bool aState) 3673 { 3674 NOREF(aState); 3675 CConsole console = mSession.GetConsole(); 3676 if (console.isOk()) 3677 { 3678 CMachineDebugger cdebugger = console.GetDebugger(); 3679 if (console.isOk()) 3680 cdebugger.SetLogEnabled (aState); 3681 } 3682 } 3683 3684 /** 3685 * Ensures that the debugger GUI instance is ready. 3686 * 3687 * @returns true if instance is fine and dandy. 3688 * @returns flase if it's not. 3689 */ 3690 bool VBoxConsoleWnd::dbgCreated() 3691 { 3692 if (mDbgGui) 3693 return true; 3694 3695 RTLDRMOD hLdrMod = vboxGlobal().getDebuggerModule(); 3696 if (hLdrMod == NIL_RTLDRMOD) 3697 return false; 3698 3699 PFNDBGGUICREATE pfnGuiCreate; 3700 int rc = RTLdrGetSymbol (hLdrMod, "DBGGuiCreate", (void**) &pfnGuiCreate); 3701 if (RT_SUCCESS (rc)) 3702 { 3703 ISession *pISession = mSession.raw(); 3704 rc = pfnGuiCreate (pISession, &mDbgGui, &mDbgGuiVT); 3705 if (RT_SUCCESS (rc)) 3706 { 3707 if (DBGGUIVT_ARE_VERSIONS_COMPATIBLE (mDbgGuiVT->u32Version, DBGGUIVT_VERSION) || 3708 mDbgGuiVT->u32EndVersion == mDbgGuiVT->u32Version) 3709 { 3710 mDbgGuiVT->pfnSetParent (mDbgGui, (QWidget*) this); 3711 mDbgGuiVT->pfnSetMenu (mDbgGui, (QMenu*) mDbgMenu); 3712 dbgAdjustRelativePos(); 3713 return true; 3714 } 3715 3716 LogRel (("DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n", 3717 mDbgGuiVT->u32Version, mDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION)); 3718 } 3719 else 3720 LogRel (("DBGGuiCreate failed, rc=%Rrc\n", rc)); 3721 } 3722 else 3723 LogRel (("RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc)); 3724 3725 mDbgGui = 0; 3726 mDbgGuiVT = 0; 3727 return false; 3728 } 3729 3730 /** 3731 * Destroys the debugger GUI instacne if it has been created. 3732 */ 3733 void VBoxConsoleWnd::dbgDestroy() 3734 { 3735 if (mDbgGui) 3736 { 3737 mDbgGuiVT->pfnDestroy (mDbgGui); 3738 mDbgGui = 0; 3739 mDbgGuiVT = 0; 3740 } 3741 } 3742 3743 /** 3744 * Tells the debugger GUI that the console window has moved or been resized. 3745 */ 3746 void VBoxConsoleWnd::dbgAdjustRelativePos() 3747 { 3748 if (mDbgGui) 3749 { 3750 QRect rct = frameGeometry(); 3751 mDbgGuiVT->pfnAdjustRelativePos (mDbgGui, rct.x(), rct.y(), rct.width(), rct.height()); 3752 } 3753 } 3754 3755 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3756 3757 VBoxNetworkDialog::VBoxNetworkDialog (QWidget *aParent, CSession &aSession) 3758 : QIWithRetranslateUI <QDialog> (aParent) 3759 , mSettings (0) 3760 , mSession (aSession) 3761 { 3762 setModal (true); 3763 /* Setup Dialog's options */ 3764 setWindowIcon (QIcon (":/nw_16px.png")); 3765 setSizeGripEnabled (true); 3766 3767 /* Setup main dialog's layout */ 3768 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3769 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3770 mainLayout->setSpacing (10); 3771 3772 /* Setup settings layout */ 3773 mSettings = new VBoxVMSettingsNetworkPage (true); 3774 mSettings->setOrderAfter (this); 3775 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3776 mSettings->getFrom (aSession.GetMachine()); 3777 mainLayout->addWidget (mSettings); 3778 3779 /* Setup button's layout */ 3780 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3781 3782 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3783 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3784 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3785 mainLayout->addWidget (buttonBox); 3786 3787 retranslateUi(); 3788 } 3789 3790 void VBoxNetworkDialog::retranslateUi() 3791 { 3792 setWindowTitle (tr ("Network Adapters")); 3793 } 3794 3795 void VBoxNetworkDialog::accept() 3796 { 3797 mSettings->putBackTo(); 3798 CMachine machine = mSession.GetMachine(); 3799 machine.SaveSettings(); 3800 if (!machine.isOk()) 3801 vboxProblem().cannotSaveMachineSettings (machine); 3802 QDialog::accept(); 3803 } 3804 3805 void VBoxNetworkDialog::showEvent (QShowEvent *aEvent) 3806 { 3807 resize (450, 300); 3808 VBoxGlobal::centerWidget (this, parentWidget()); 3809 setMinimumWidth (400); 3810 QDialog::showEvent (aEvent); 3811 } 3812 3813 VBoxSFDialog::VBoxSFDialog (QWidget *aParent, CSession &aSession) 3814 : QIWithRetranslateUI <QDialog> (aParent) 3815 , mSettings (0) 3816 , mSession (aSession) 3817 { 3818 setModal (true); 3819 /* Setup Dialog's options */ 3820 setWindowIcon (QIcon (":/select_file_16px.png")); 3821 setSizeGripEnabled (true); 3822 3823 /* Setup main dialog's layout */ 3824 QVBoxLayout *mainLayout = new QVBoxLayout (this); 3825 VBoxGlobal::setLayoutMargin (mainLayout, 10); 3826 mainLayout->setSpacing (10); 3827 3828 /* Setup settings layout */ 3829 mSettings = new VBoxVMSettingsSF (MachineType | ConsoleType, this); 3830 VBoxGlobal::setLayoutMargin (mSettings->layout(), 0); 3831 mSettings->getFromConsole (aSession.GetConsole()); 3832 mSettings->getFromMachine (aSession.GetMachine()); 3833 mainLayout->addWidget (mSettings); 3834 3835 /* Setup button's layout */ 3836 QIDialogButtonBox *buttonBox = new QIDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 3837 3838 connect (buttonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog())); 3839 connect (buttonBox, SIGNAL (accepted()), this, SLOT (accept())); 3840 connect (buttonBox, SIGNAL (rejected()), this, SLOT (reject())); 3841 mainLayout->addWidget (buttonBox); 3842 3843 retranslateUi(); 3844 } 3845 3846 void VBoxSFDialog::retranslateUi() 3847 { 3848 setWindowTitle (tr ("Shared Folders")); 3849 } 3850 3851 void VBoxSFDialog::accept() 3852 { 3853 mSettings->putBackToConsole(); 3854 mSettings->putBackToMachine(); 3855 CMachine machine = mSession.GetMachine(); 3856 machine.SaveSettings(); 3857 if (!machine.isOk()) 3858 vboxProblem().cannotSaveMachineSettings (machine); 3859 QDialog::accept(); 3860 } 3861 3862 void VBoxSFDialog::showEvent (QShowEvent *aEvent) 3863 { 3864 resize (450, 300); 3865 VBoxGlobal::centerWidget (this, parentWidget()); 3866 setMinimumWidth (400); 3867 QDialog::showEvent (aEvent); 3868 } 3869 3870 #include "VBoxConsoleWnd.moc" 764 { 765 /* Toggle USB LED: */ 766 indicatorsPool()->indicator(UIIndicatorIndex_USBDevices)->setState( 767 usbController.GetEnabled() ? KDeviceActivity_Idle : KDeviceActivity_Null); 768 } 769 } 770 771 /* Global settings */ 772 { 773 VBoxGlobalSettings settings = vboxGlobal().settings(); 774 menuBar()->setHidden(settings.isFeatureActive("noMenuBar")); 775 statusBar()->setHidden(settings.isFeatureActive("noStatusBar")); 776 } 777 } 778 779 void UIMachineWindowNormal::saveWindowSettings() 780 { 781 CMachine machine = machineLogic()->session().GetMachine(); 782 783 /* Extra-data settings */ 784 { 785 QString strWindowPosition = QString("%1,%2,%3,%4") 786 .arg(m_normalGeometry.x()).arg(m_normalGeometry.y()) 787 .arg(m_normalGeometry.width()).arg(m_normalGeometry.height()); 788 if (isMaximized()) 789 strWindowPosition += QString(",%1").arg(VBoxDefs::GUI_LastWindowPosition_Max); 790 machine.SetExtraData(VBoxDefs::GUI_LastWindowPosition, strWindowPosition); 791 } 792 } 793 794 void UIMachineWindowNormal::cleanupStatusBar() 795 { 796 /* Stop LED-update timer: */ 797 m_pIdleTimer->stop(); 798 m_pIdleTimer->disconnect(SIGNAL(timeout()), this, SLOT(updateDeviceLights())); 799 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.h
r26537 r26637 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxConsoleWndclass declaration4 * UIMachineWindowNormal class declaration 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2009Sun Microsystems, Inc.8 * Copyright (C) 2010 Sun Microsystems, Inc. 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 */ 22 22 23 #ifndef __ VBoxConsoleWnd_h__24 #define __ VBoxConsoleWnd_h__23 #ifndef __UIMachineWindowNormal_h__ 24 #define __UIMachineWindowNormal_h__ 25 25 26 26 /* Global includes */ 27 #include <QColor> 28 #include <QDialog> 29 #include <QMainWindow> 30 #include <QMap> 31 #include <QMenu> 32 #include <QPointer> 27 #include <QLabel> 33 28 34 29 /* Local includes */ 35 #include " COMDefs.h"30 #include "VBoxDefs.h" 36 31 #include "QIWithRetranslateUI.h" 37 #include "VBoxProblemReporter.h" 38 #include "VBoxHelpActions.h" 39 40 #ifdef VBOX_WITH_DEBUGGER_GUI 41 # include <VBox/dbggui.h> 42 #endif 43 #ifdef Q_WS_MAC 44 # include <ApplicationServices/ApplicationServices.h> 45 # ifndef QT_MAC_USE_COCOA 46 # include <Carbon/Carbon.h> 47 # endif /* !QT_MAC_USE_COCOA */ 32 #include "QIMainDialog.h" 33 #include "UIMachineWindow.h" 34 #ifdef Q_WS_X11 35 # include <X11/Xlib.h> 48 36 #endif 49 37 50 /* Global forwards */ 51 class QAction; 52 class QActionGroup; 53 class QLabel; 54 class QSpacerItem; 55 class QIWidgetValidator; 38 /* Local forwards */ 39 class UIIndicatorsPool; 40 class QIStateIndicator; 56 41 57 /* Local forwards */ 58 class QIMenu; 59 class QIStateIndicator; 60 class VBoxChangeDockIconUpdateEvent; 61 class VBoxChangePresentationModeEvent; 62 class VBoxConsoleView; 63 class VBoxMiniToolBar; 64 class VBoxSwitchMenu; 65 class VBoxUSBMenu; 66 67 class VBoxConsoleWnd : public QIWithRetranslateUI2 <QMainWindow> 42 class UIMachineWindowNormal : public QIWithRetranslateUI<QIMainDialog>, public UIMachineWindow 68 43 { 69 44 Q_OBJECT; 70 45 71 public:72 73 VBoxConsoleWnd (VBoxConsoleWnd **aSelf, QWidget* aParent = 0, Qt::WindowFlags aFlags = Qt::Window);74 virtual ~VBoxConsoleWnd();75 76 bool isWindowMaximized() const77 {78 #ifdef Q_WS_MAC79 /* On Mac OS X we didn't really jump to the fullscreen mode but80 * maximize the window. This situation has to be considered when81 * checking for maximized or fullscreen mode. */82 return !isTrueSeamless() && QMainWindow::isMaximized();83 #else /* Q_WS_MAC */84 return QMainWindow::isMaximized();85 #endif /* Q_WS_MAC */86 }87 bool isWindowFullScreen() const88 {89 #ifdef Q_WS_MAC90 /* On Mac OS X we didn't really jump to the fullscreen mode but91 * maximize the window. This situation has to be considered when92 * checking for maximized or fullscreen mode. */93 return isTrueFullscreen() || isTrueSeamless();94 #else /* Q_WS_MAC */95 return QMainWindow::isFullScreen();96 #endif /* Q_WS_MAC */97 }98 bool isTrueFullscreen() const { return mIsFullscreen; }99 bool isTrueSeamless() const { return mIsSeamless; }100 101 KMachineState machineState() const { return mMachineState; }102 103 bool openView (const CSession &aSession);104 105 void setMouseIntegrationLocked (bool aDisabled);106 107 void popupMainMenu (bool aCenter);108 109 void installGuestAdditionsFrom (const QString &aSource);110 111 void setMask (const QRegion &aRegion);112 void clearMask();113 114 /* informs that the guest display is resized */115 void onDisplayResize (ulong aHeight, ulong aWidth);116 117 #ifdef VBOX_WITH_VIDEOHWACCEL118 /* used for obtaining the extradata settings */119 CSession &session() { return mSession; }120 #endif121 signals:122 123 void closing();124 125 46 protected: 126 47 127 bool event (QEvent *aEvent); 128 void closeEvent (QCloseEvent *aEvent); 129 #ifdef Q_WS_X11 130 bool x11Event (XEvent *aEvent); 131 #endif 132 133 void retranslateUi(); 48 UIMachineWindowNormal(UIMachineLogic *pMachineLogic); 49 virtual ~UIMachineWindowNormal(); 134 50 135 51 private slots: 136 52 137 void finalizeOpenView(); 138 void tryClose(); 53 void sltTryClose(); 139 54 140 void vmFullscreen (bool aOn); 141 void vmSeamless (bool aOn); 142 void vmAutoresizeGuest (bool aOn); 143 void vmAdjustWindow(); 144 void vmDisableMouseIntegration (bool aOff); 145 void vmTypeCAD(); 146 #ifdef Q_WS_X11 147 void vmTypeCABS(); 55 void sltPrepareMenuMachine(); 56 void sltPrepareMenuDevices(); 57 #ifdef VBOX_WITH_DEBUGGER_GUI 58 void sltPrepareMenuDebug(); 148 59 #endif 149 void vmTakeSnapshot();150 void vmShowInfoDialog();151 void vmReset();152 void vmPause (bool aOn);153 void vmACPIShutdown();154 void vmClose();155 60 156 void devicesSwitchVrdp (bool aOn); 157 void devicesOpenNetworkDialog(); 158 void devicesOpenSFDialog(); 159 void devicesInstallGuestAdditions(); 61 void sltUpdateIndicators(); 62 void sltShowIndicatorsContextMenu(QIStateIndicator *pIndicator, QContextMenuEvent *pEvent); 160 63 161 void prepareStorageMenu(); 162 void prepareNetworkMenu(); 163 void prepareSFMenu(); 64 void sltProcessGlobalSettingChange(const char *aPublicName, const char *aName); 164 65 165 void mountMedium(); 166 void switchUSB (QAction *aAction); 167 168 void showIndicatorContextMenu (QIStateIndicator *aInd, QContextMenuEvent *aEvent); 169 170 void updateDeviceLights(); 171 void updateMachineState (KMachineState aState); 172 void updateMouseState (int aState); 173 void updateAdditionsState (const QString &aVersion, bool aActive, 174 bool aSeamlessSupported, bool aGraphicsSupported); 175 void updateNetworkAdaptersState(); 176 void updateUsbState(); 177 void updateMediaDriveState (VBoxDefs::MediumType aType); 178 void updateSharedFoldersState(); 179 180 void onExitFullscreen(); 181 void unlockActionsSwitch(); 182 183 void mtExitMode(); 184 void mtCloseVM(); 185 void mtMaskUpdate(); 186 187 void changeDockIconUpdate (const VBoxChangeDockIconUpdateEvent &aEvent); 188 void changePresentationMode (const VBoxChangePresentationModeEvent &aEvent); 189 void processGlobalSettingChange (const char *aPublicName, const char *aName); 190 191 #ifdef VBOX_WITH_DEBUGGER_GUI 192 void dbgPrepareDebugMenu(); 193 void dbgShowStatistics(); 194 void dbgShowCommandLine(); 195 void dbgLoggingToggled (bool aBool); 196 #endif 66 void sltUpdateMediaDriveState(VBoxDefs::MediumType type); 67 void sltUpdateNetworkAdaptersState(); 68 void sltUpdateUsbState(); 69 void sltUpdateSharedFoldersState(); 70 void sltUpdateMouseState(int iState); 197 71 198 72 private: 199 73 200 enum /* Stuff */ 201 { 202 HardDiskStuff = 0x01, 203 DVDStuff = 0x02, 204 FloppyStuff = 0x04, 205 PauseAction = 0x08, 206 NetworkStuff = 0x10, 207 DisableMouseIntegrAction = 0x20, 208 Caption = 0x40, 209 USBStuff = 0x80, 210 VRDPStuff = 0x100, 211 SharedFolderStuff = 0x200, 212 VirtualizationStuff = 0x400, 213 AllStuff = 0xFFFF, 214 }; 74 /* Translate routine: */ 75 void retranslateUi(); 215 76 216 void checkRequiredFeatures();217 void activateUICustomizations();77 /* Update routines: */ 78 void updateAppearanceOf(int aElement); 218 79 219 void updateAppearanceOf (int aElement); 220 221 bool toggleFullscreenMode (bool aOn, bool aSeamless); 222 void switchToFullscreen (bool aOn, bool aSeamless); 223 void setViewInSeamlessMode (const QRect &aTargetRect); 224 225 void closeView(); 226 227 #ifdef VBOX_WITH_DEBUGGER_GUI 228 bool dbgCreated(); 229 void dbgDestroy(); 230 void dbgAdjustRelativePos(); 80 /* Event handlers: */ 81 bool event(QEvent *pEvent); 82 #ifdef Q_WS_X11 83 bool x11Event(XEvent *pEvent); 231 84 #endif 232 85 233 /* COM Variables*/234 CSession mSession;86 /* Private getters: */ 87 UIIndicatorsPool* indicatorsPool() { return m_pIndicatorsPool; } 235 88 236 /* Machine State */ 237 KMachineState mMachineState; 89 /* Prepare helpers: */ 90 void prepareMenu(); 91 void prepareStatusBar(); 92 void prepareConnections(); 93 void prepareMachineView(); 94 void loadWindowSettings(); 238 95 239 /* Window Variables */ 240 QString mCaptionPrefix; 241 int mConsoleStyle; 96 /* Cleanup helpers: */ 97 void saveWindowSettings(); 98 //void cleanupMachineView(); 99 //void cleanupConnections(); 100 void cleanupStatusBar(); 101 //void cleanupMenu(); 242 102 243 /* Menu items */ 244 QIMenu *mMainMenu; 245 QMenu *mVMMenu; 246 QMenu *mVMMenuMini; 247 QMenu *mDevicesMenu; 248 QMenu *mDevicesCDMenu; 249 QMenu *mDevicesFDMenu; 250 QMenu *mDevicesNetworkMenu; 251 QMenu *mDevicesSFMenu; 252 VBoxUSBMenu *mDevicesUSBMenu; 253 VBoxSwitchMenu *mVmDisMouseIntegrMenu; 254 #if 0 /* todo: allow to setup */ 255 VBoxSwitchMenu *mDevicesVRDPMenu; 256 VBoxSwitchMenu *mVmAutoresizeMenu; 257 #endif 258 #ifdef VBOX_WITH_DEBUGGER_GUI 259 QMenu *mDbgMenu; 260 #endif 261 QMenu *mHelpMenu; 103 /* Indicators pool: */ 104 UIIndicatorsPool *m_pIndicatorsPool; 105 /* Other QWidgets: */ 106 QWidget *m_pCntHostkey; 107 QLabel *m_pNameHostkey; 108 /* Other QObjects: */ 109 QTimer *m_pIdleTimer; 110 /* Other members: */ 111 QRect m_normalGeometry; 262 112 263 QActionGroup *mRunningActions; 264 QActionGroup *mRunningOrPausedActions; 265 266 /* Machine actions */ 267 QAction *mVmFullscreenAction; 268 QAction *mVmSeamlessAction; 269 QAction *mVmAutoresizeGuestAction; 270 QAction *mVmAdjustWindowAction; 271 QAction *mVmDisableMouseIntegrAction; 272 QAction *mVmTypeCADAction; 273 #ifdef Q_WS_X11 274 QAction *mVmTypeCABSAction; 275 #endif 276 QAction *mVmTakeSnapshotAction; 277 QAction *mVmShowInformationDlgAction; 278 QAction *mVmResetAction; 279 QAction *mVmPauseAction; 280 QAction *mVmACPIShutdownAction; 281 QAction *mVmCloseAction; 282 283 /* Devices actions */ 284 QAction *mDevicesNetworkDialogAction; 285 QAction *mDevicesSFDialogAction; 286 QAction *mDevicesSwitchVrdpSeparator; 287 QAction *mDevicesSwitchVrdpAction; 288 QAction *mDevicesInstallGuestToolsAction; 289 290 #ifdef VBOX_WITH_DEBUGGER_GUI 291 /* Debugger actions */ 292 QAction *mDbgStatisticsAction; 293 QAction *mDbgCommandLineAction; 294 QAction *mDbgLoggingAction; 295 #endif 296 297 /* Help actions */ 298 VBoxHelpActions mHelpActions; 299 300 /* Widgets */ 301 VBoxConsoleView *mConsole; 302 VBoxMiniToolBar *mMiniToolBar; 303 #ifdef VBOX_WITH_DEBUGGER_GUI 304 /** The handle to the debugger gui. */ 305 PDBGGUI mDbgGui; 306 /** The virtual method table for the debugger GUI. */ 307 PCDBGGUIVT mDbgGuiVT; 308 #endif 309 310 /* Timer to update LEDs */ 311 QTimer *mIdleTimer; 312 313 /* LEDs */ 314 QIStateIndicator *mHDLed; 315 QIStateIndicator *mCDLed; 316 #if 0 /* todo: allow to setup */ 317 QIStateIndicator *mFDLed; 318 #endif 319 QIStateIndicator *mNetLed; 320 QIStateIndicator *mUSBLed; 321 QIStateIndicator *mSFLed; 322 QIStateIndicator *mVirtLed; 323 QIStateIndicator *mMouseLed; 324 QIStateIndicator *mHostkeyLed; 325 QWidget *mHostkeyLedContainer; 326 QLabel *mHostkeyName; 327 #if 0 /* todo: allow to setup */ 328 QIStateIndicator *mVrdpLed; 329 QIStateIndicator *mAutoresizeLed; 330 #endif 331 332 /* Normal Mode */ 333 QRect mNormalGeo; 334 335 /* Fullscreen/Seamless Mode */ 336 QList < QPointer <QWidget> > mHiddenChildren; 337 QSpacerItem *mShiftingSpacerLeft; 338 QSpacerItem *mShiftingSpacerTop; 339 QSpacerItem *mShiftingSpacerRight; 340 QSpacerItem *mShiftingSpacerBottom; 341 QPalette mErasePalette; 342 QSize mPrevMinSize; 343 QSize mMaskShift; 344 QRegion mStrictedRegion; 345 #ifdef Q_WS_WIN 346 QRegion mPrevRegion; 347 #endif 348 #ifdef Q_WS_MAC 349 //QRegion mCurrRegion; 350 # ifndef QT_MAC_USE_COCOA 351 //EventHandlerRef mDarwinRegionEventHandlerRef; 352 # endif 353 /* For seamless maximizing */ 354 QRect mNormalGeometry; 355 Qt::WindowFlags mSavedFlags; 356 /* For the fade effect if the the window goes fullscreen */ 357 CGDisplayFadeReservationToken mFadeToken; 358 #endif 359 360 /* Different bool flags */ 361 bool mIsOpenViewFinished : 1; 362 bool mIsFirstTimeStarted : 1; 363 bool mIsAutoSaveMedia : 1; 364 bool mNoAutoClose : 1; 365 bool mIsFullscreen : 1; 366 bool mIsSeamless : 1; 367 bool mIsSeamlessSupported : 1; 368 bool mIsGraphicsSupported : 1; 369 bool mIsWaitingModeResize : 1; 370 bool mWasMax : 1; 113 /* Factory support: */ 114 friend class UIMachineWindow; 371 115 }; 372 116 373 /* We want to make the first action highlighted but not 374 * selected, but Qt makes the both or neither one of this, 375 * so, just move the focus to the next eligible object, 376 * which will be the first menu action. This little 377 * subclass made only for that purpose. */ 378 class QIMenu : public QMenu 379 { 380 Q_OBJECT; 381 382 public: 383 384 QIMenu (QWidget *aParent) : QMenu (aParent) {} 385 386 void selectFirstAction() { QMenu::focusNextChild(); } 387 }; 388 389 class VBoxSettingsPage; 390 class VBoxNetworkDialog : public QIWithRetranslateUI <QDialog> 391 { 392 Q_OBJECT; 393 394 public: 395 396 VBoxNetworkDialog (QWidget *aParent, CSession &aSession); 397 398 protected: 399 400 void retranslateUi(); 401 402 protected slots: 403 404 virtual void accept(); 405 406 protected: 407 408 void showEvent (QShowEvent *aEvent); 409 410 private: 411 412 VBoxSettingsPage *mSettings; 413 CSession &mSession; 414 }; 415 416 class VBoxVMSettingsSF; 417 class VBoxSFDialog : public QIWithRetranslateUI <QDialog> 418 { 419 Q_OBJECT; 420 421 public: 422 423 VBoxSFDialog (QWidget *aParent, CSession &aSession); 424 425 protected: 426 427 void retranslateUi(); 428 429 protected slots: 430 431 virtual void accept(); 432 433 protected: 434 435 void showEvent (QShowEvent *aEvent); 436 437 private: 438 439 VBoxVMSettingsSF *mSettings; 440 CSession &mSession; 441 }; 442 443 #endif // __VBoxConsoleWnd_h__ 117 #endif // __UIMachineWindowNormal_h__
Note:
See TracChangeset
for help on using the changeset viewer.