- Timestamp:
- Feb 24, 2010 4:34:48 PM (15 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/runtime
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r26709 r26754 403 403 connect(uisession(), SIGNAL(sigStateChange(KMachineState)), this, SLOT(sltMachineStateChanged(KMachineState))); 404 404 connect(uisession(), SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged())); 405 connect(uisession(), SIGNAL(sigUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)), 406 this, SLOT(sltUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &))); 407 connect(uisession(), SIGNAL(sigRuntimeError(bool, const QString &, const QString &)), 408 this, SLOT(sltRuntimeError(bool, const QString &, const QString &))); 405 409 } 406 410 … … 800 804 } 801 805 806 void UIMachineLogic::sltUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error) 807 { 808 bool success = error.isNull(); 809 810 if (!success) 811 { 812 if (bIsAttached) 813 vboxProblem().cannotAttachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error); 814 else 815 vboxProblem().cannotDetachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error); 816 } 817 } 818 819 void UIMachineLogic::sltRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage) 820 { 821 vboxProblem().showRuntimeError(session().GetConsole(), bIsFatal, strErrorId, strMessage); 822 } 823 802 824 void UIMachineLogic::sltToggleGuestAutoresize(bool /* bEnabled */) 803 825 { -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
r26709 r26754 77 77 78 78 /* Cleanup helpers: */ 79 v oid saveLogicSettings();80 //v oid cleanupRequiredFeatures();81 //v oid cleanupActionConnections();82 //v oid cleanupActionGroups();83 //v oid cleanupConsoleConnections();79 virtual void saveLogicSettings(); 80 //virtual void cleanupRequiredFeatures(); 81 //virtual void cleanupActionConnections(); 82 //virtual void cleanupActionGroups(); 83 //virtual void cleanupConsoleConnections(); 84 84 85 85 /* Protected getters: */ … … 105 105 void sltMachineStateChanged(KMachineState newMachineState); 106 106 void sltAdditionsStateChanged(); 107 void sltUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error); 108 void sltRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage); 107 109 108 110 /* "Machine" menu funtionality */ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
r26730 r26754 119 119 }; 120 120 121 enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 }; 122 enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 }; 123 121 124 UIMachineView* UIMachineView::create( UIMachineWindow *pMachineWindow 122 125 , VBoxDefs::RenderMode renderMode … … 197 200 ) 198 201 : QAbstractScrollArea(pMachineWindow->machineWindow()) 199 /* Protected members: */200 , mode(renderMode)201 , m_bIsGuestSupportsGraphics(false)202 202 /* Private members: */ 203 203 , m_pMachineWindow(pMachineWindow) 204 204 , m_console(pMachineWindow->machineLogic()->uisession()->session().GetConsole()) 205 , m_mode(renderMode) 205 206 , m_globalSettings(vboxGlobal().settings()) 207 , m_machineState(KMachineState_Null) 208 , m_pFrameBuffer(0) 209 #if defined(Q_WS_WIN) 210 , m_alphaCursor(0) 211 #endif 206 212 , m_iLastMouseWheelDelta(0) 207 , m uNumLockAdaptionCnt(2)208 , m uCapsLockAdaptionCnt(2)213 , m_uNumLockAdaptionCnt(2) 214 , m_uCapsLockAdaptionCnt(2) 209 215 , m_bIsAutoCaptureDisabled(false) 210 216 , m_bIsKeyboardCaptured(false) … … 214 220 , m_bIsHostkeyPressed(false) 215 221 , m_bIsHostkeyAlone (false) 222 , m_bIsGuestSupportsGraphics(false) 216 223 , m_bIsMachineWindowResizeIgnored(true) 217 224 , m_bIsFrameBufferResizeIgnored(false) 218 225 , m_bIsGuestResizeIgnored(false) 226 , m_numLock(false) 227 , m_scrollLock(false) 228 , m_capsLock(false) 229 , m_fPassCAD (false) 230 , m_fHideHostPointer(true) 231 #ifdef VBOX_WITH_VIDEOHWACCEL 232 , m_fAccelerate2DVideo(bAccelerate2DVideo) 233 #endif 234 #if 0 // TODO: Do we need this? 219 235 , mDoResize(false) 220 , mNumLock(false)221 , mScrollLock(false)222 , mCapsLock(false)223 #ifdef VBOX_WITH_VIDEOHWACCEL224 , mAccelerate2DVideo(bAccelerate2DVideo)225 #endif226 #if defined(Q_WS_WIN)227 , mAlphaCursor (NULL)228 236 #endif 229 237 #if defined(Q_WS_MAC) 230 238 # ifndef QT_MAC_USE_COCOA 231 , m DarwinEventHandlerRef(NULL)239 , m_darwinEventHandlerRef(NULL) 232 240 # endif /* !QT_MAC_USE_COCOA */ 233 , m DarwinKeyModifiers (0)234 , m KeyboardGrabbed (false)241 , m_darwinKeyModifiers (0) 242 , m_fKeyboardGrabbed (false) 235 243 , mDockIconEnabled (true) 236 244 #endif 237 , mDesktopGeo (DesktopGeo_Invalid) 238 , mPassCAD (false) 245 , m_desktopGeometryType(DesktopGeo_Invalid) 239 246 /* Don't show a hardware pointer until we have one to show */ 240 , mHideHostPointer (true)241 247 { 242 248 } … … 252 258 /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done 253 259 * by DevVGA if provoked before power on. */ 254 QSize fb(m FrameBuf->width(), mFrameBuf->height());260 QSize fb(m_pFrameBuffer->width(), m_pFrameBuffer->height()); 255 261 if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled())) 256 262 fb = QSize(640, 480); 257 263 return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2); 258 264 #else 259 return QSize(m FrameBuf->width() + frameWidth() * 2, mFrameBuf->height() + frameWidth() * 2);265 return QSize(m_pFrameBuffer->width() + frameWidth() * 2, m_pFrameBuffer->height() + frameWidth() * 2); 260 266 #endif 261 267 } … … 273 279 int UIMachineView::contentsWidth() const 274 280 { 275 return m FrameBuf->width();281 return m_pFrameBuffer->width(); 276 282 } 277 283 278 284 int UIMachineView::contentsHeight() const 279 285 { 280 return m FrameBuf->height();286 return m_pFrameBuffer->height(); 281 287 } 282 288 … … 291 297 } 292 298 299 QRect UIMachineView::desktopGeometry() const 300 { 301 QRect geometry; 302 switch (m_desktopGeometryType) 303 { 304 case DesktopGeo_Fixed: 305 case DesktopGeo_Automatic: 306 geometry = QRect(0, 0, 307 qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()), 308 qMax(m_desktopGeometry.height(), m_storedConsoleSize.height())); 309 break; 310 case DesktopGeo_Any: 311 geometry = QRect(0, 0, 0, 0); 312 break; 313 default: 314 AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType)); 315 } 316 return geometry; 317 } 318 293 319 void UIMachineView::calculateDesktopGeometry() 294 320 { 295 /* This method should not get called until we have initially set up the m DesktopGeo: */296 Assert((m DesktopGeo!= DesktopGeo_Invalid));321 /* This method should not get called until we have initially set up the m_desktopGeometryType: */ 322 Assert((m_desktopGeometryType != DesktopGeo_Invalid)); 297 323 /* If we are not doing automatic geometry calculation then there is nothing to do: */ 298 if (DesktopGeo_Automatic == m DesktopGeo)324 if (DesktopGeo_Automatic == m_desktopGeometryType) 299 325 { 300 326 /* Available geometry of the desktop. If the desktop is a single … … 303 329 * complex case of a desktop spanning multiple screens: */ 304 330 QRect desktop = availableGeometry(); 305 /* The area taken up by the console window on the desktop,306 * including window frame, title and menu bar and whatnot .*/331 /* The area taken up by the machine window on the desktop, 332 * including window frame, title and menu bar and whatnot: */ 307 333 QRect frame = machineWindowWrapper()->machineWindow()->frameGeometry(); 308 /* The area taken up by the console window, minus all decorations.*/334 /* The area taken up by the machine view, so excluding all decorations: */ 309 335 QRect window = geometry(); 310 336 /* To work out how big we can make the console window while still … … 312 338 * This works because the difference between frame and window 313 339 * (or at least its width and height) is a constant. */ 314 m DesktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(),340 m_desktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(), 315 341 desktop.height() - frame.height() + window.height()); 316 342 } 317 343 } 318 344 319 QRect UIMachineView::desktopGeometry() const 320 { 321 QRect rc; 322 switch (mDesktopGeo) 345 void UIMachineView::setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight) 346 { 347 switch (aGeo) 323 348 { 324 349 case DesktopGeo_Fixed: 350 m_desktopGeometryType = DesktopGeo_Fixed; 351 if (aWidth != 0 && aHeight != 0) 352 m_desktopGeometry = QRect(0, 0, aWidth, aHeight); 353 else 354 m_desktopGeometry = QRect(0, 0, 0, 0); 355 storeConsoleSize(0, 0); 356 break; 325 357 case DesktopGeo_Automatic: 326 rc = QRect(0, 0,327 qMax(mDesktopGeometry.width(), mStoredConsoleSize.width()),328 qMax(mDesktopGeometry.height(), mStoredConsoleSize.height()));358 m_desktopGeometryType = DesktopGeo_Automatic; 359 m_desktopGeometry = QRect(0, 0, 0, 0); 360 storeConsoleSize(0, 0); 329 361 break; 330 362 case DesktopGeo_Any: 331 rc = QRect(0, 0, 0, 0); 363 m_desktopGeometryType = DesktopGeo_Any; 364 m_desktopGeometry = QRect(0, 0, 0, 0); 332 365 break; 333 366 default: 334 AssertMsgFailed(("Bad geometry type %d\n", mDesktopGeo)); 335 } 336 return rc; 367 AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo)); 368 m_desktopGeometryType = DesktopGeo_Invalid; 369 } 370 } 371 372 void UIMachineView::storeConsoleSize(int aWidth, int aHeight) 373 { 374 LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight)); 375 m_storedConsoleSize = QRect(0, 0, aWidth, aHeight); 376 } 377 378 QRect UIMachineView::availableGeometry() 379 { 380 return machineWindowWrapper()->machineWindow()->isFullScreen() ? 381 QApplication::desktop()->screenGeometry(this) : 382 QApplication::desktop()->availableGeometry(this); 337 383 } 338 384 … … 341 387 CDisplay display = m_console.GetDisplay(); 342 388 Assert(!display.isNull()); 343 m FrameBuf= NULL;344 345 switch (mode )389 m_pFrameBuffer = NULL; 390 391 switch (mode()) 346 392 { 347 393 #if defined (VBOX_GUI_USE_QIMAGE) … … 349 395 #if 0 // TODO: Enable QImage + Video Acceleration! 350 396 # ifdef VBOX_WITH_VIDEOHWACCEL 351 m FrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UIFrameBufferQImage>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQImage(this);397 m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UIFrameBufferQImage>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQImage(this); 352 398 # else 353 m FrameBuf= new UIFrameBufferQImage(this);399 m_pFrameBuffer = new UIFrameBufferQImage(this); 354 400 # endif 355 401 #endif 356 m FrameBuf= new UIFrameBufferQImage(this);402 m_pFrameBuffer = new UIFrameBufferQImage(this); 357 403 break; 358 404 #endif … … 360 406 #if defined (VBOX_GUI_USE_QGL) 361 407 case VBoxDefs::QGLMode: 362 m FrameBuf= new UIQGLFrameBuffer(this);408 m_pFrameBuffer = new UIQGLFrameBuffer(this); 363 409 break; 364 410 case VBoxDefs::QGLOverlayMode: 365 m FrameBuf= new UIQGLOverlayFrameBuffer(this);411 m_pFrameBuffer = new UIQGLOverlayFrameBuffer(this); 366 412 break; 367 413 #endif … … 377 423 # endif 378 424 # if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */ 379 m FrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UISDLFrameBuffer> (this, &machineWindowWrapper()->session()) : new UISDLFrameBuffer(this);425 m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UISDLFrameBuffer> (this, &machineWindowWrapper()->session()) : new UISDLFrameBuffer(this); 380 426 # else 381 m FrameBuf= new UISDLFrameBuffer(this);427 m_pFrameBuffer = new UISDLFrameBuffer(this); 382 428 # endif 383 429 /* Disable scrollbars because we cannot correctly draw in a scrolled window using SDL: */ … … 390 436 #if defined (VBOX_GUI_USE_DDRAW) 391 437 case VBoxDefs::DDRAWMode: 392 m FrameBuf= new UIDDRAWFrameBuffer(this);393 if (!m FrameBuf || mFrameBuf->address() == NULL)394 { 395 if (m FrameBuf)396 delete m FrameBuf;397 m ode = VBoxDefs::QImageMode;398 m FrameBuf= new UIFrameBufferQImage(this);438 m_pFrameBuffer = new UIDDRAWFrameBuffer(this); 439 if (!m_pFrameBuffer || m_pFrameBuffer->address() == NULL) 440 { 441 if (m_pFrameBuffer) 442 delete m_pFrameBuffer; 443 m_mode = VBoxDefs::QImageMode; 444 m_pFrameBuffer = new UIFrameBufferQImage(this); 399 445 } 400 446 break; … … 407 453 pViewport->setAttribute(Qt::WA_PaintOnScreen); 408 454 # ifdef VBOX_WITH_VIDEOHWACCEL 409 m FrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQuartz2D(this);455 m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQuartz2D(this); 410 456 # else 411 m FrameBuf= new UIFrameBufferQuartz2D(this);457 m_pFrameBuffer = new UIFrameBufferQuartz2D(this); 412 458 # endif 413 459 break; … … 415 461 #endif 416 462 default: 417 AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode ));418 LogRel(("Invalid render mode: %d\n", mode ));463 AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode())); 464 LogRel(("Invalid render mode: %d\n", mode())); 419 465 qApp->exit(1); 420 466 break; 421 467 } 422 if (m FrameBuf)423 { 424 m FrameBuf->AddRef();425 display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(m FrameBuf));468 if (m_pFrameBuffer) 469 { 470 m_pFrameBuffer->AddRef(); 471 display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(m_pFrameBuffer)); 426 472 } 427 473 } … … 433 479 434 480 /* Pressed keys: */ 435 ::memset(m PressedKeys, 0, sizeof(mPressedKeys));481 ::memset(m_pressedKeys, 0, sizeof(m_pressedKeys)); 436 482 437 483 /* Prepare viewport: */ 438 484 #ifdef VBOX_GUI_USE_QGL 439 485 QWidget *pViewport; 440 switch (mode )486 switch (mode()) 441 487 { 442 488 #if 0 // TODO: Create Open GL viewport! … … 521 567 viewport()->installEventFilter(this); 522 568 523 /* To fix some focus issues: */524 //qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);525 526 569 /* We want to be notified on some parent's events: */ 527 570 machineWindowWrapper()->machineWindow()->installEventFilter(this); 571 } 572 573 void UIMachineView::prepareConsoleConnections() 574 { 575 UISession *sender = machineWindowWrapper()->machineLogic()->uisession(); 576 connect(sender, SIGNAL(sigMousePointerShapeChange(bool, bool, uint, uint, uint, uint, const uchar *)), 577 this, SLOT(sltMousePointerShapeChange(bool, bool, uint, uint, uint, uint, const uchar *))); 578 connect(sender, SIGNAL(sigMouseCapabilityChange(bool, bool)), this, SLOT(sltMouseCapabilityChange(bool, bool))); 579 connect(sender, SIGNAL(sigKeyboardLedsChange(bool, bool, bool)), this, SLOT(sltKeyboardLedsChange(bool, bool, bool))); 580 connect(sender, SIGNAL(sigStateChange(KMachineState)), this, SLOT(sltStateChange(KMachineState))); 581 connect(sender, SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChange())); 528 582 } 529 583 … … 558 612 QString passCAD = m_console.GetMachine().GetExtraData(VBoxDefs::GUI_PassCAD); 559 613 if (!passCAD.isEmpty() && ((passCAD != "false") || (passCAD != "no"))) 560 m PassCAD = true;614 m_fPassCAD = true; 561 615 } 562 616 } … … 574 628 UnhookWindowsHookEx(gKbdHook); 575 629 gView = 0; 576 if (m AlphaCursor)577 DestroyIcon(m AlphaCursor);630 if (m_alphaCursor) 631 DestroyIcon(m_alphaCursor); 578 632 #endif 579 633 … … 594 648 { 595 649 /* Cleanup: */ 596 if (m FrameBuf)650 if (m_pFrameBuffer) 597 651 { 598 652 /* Detach framebuffer from Display: */ … … 600 654 display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL)); 601 655 /* Release the reference: */ 602 mFrameBuf->Release(); 603 mFrameBuf = NULL; 604 } 656 m_pFrameBuffer->Release(); 657 m_pFrameBuffer = NULL; 658 } 659 } 660 661 void UIMachineView::sltMousePointerShapeChange(bool fIsVisible, bool fHasAlpha, 662 uint uXHot, uint uYHot, uint uWidth, uint uHeight, 663 const uchar *pShapeData) 664 { 665 if (m_bIsMouseAbsolute) 666 { 667 /* Do we have new shape data? */ 668 if (pShapeData) 669 setPointerShape(pShapeData, fHasAlpha, uXHot, uYHot, uWidth, uHeight); 670 671 /* Should we hide/show pointer? */ 672 if (fIsVisible) 673 viewport()->setCursor(m_lastCursor); 674 else 675 viewport()->setCursor(Qt::BlankCursor); 676 } 677 m_fHideHostPointer = !fIsVisible; 678 } 679 680 void UIMachineView::sltMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor) 681 { 682 if (m_bIsMouseAbsolute != bIsSupportsAbsolute) 683 { 684 m_bIsMouseAbsolute = bIsSupportsAbsolute; 685 /* Correct the mouse capture state and reset the cursor to the default shape if necessary: */ 686 if (m_bIsMouseAbsolute) 687 { 688 CMouse mouse = m_console.GetMouse(); 689 mouse.PutMouseEventAbsolute(-1, -1, 0, 0 /* Horizontal wheel */, 0); 690 captureMouse(false, false); 691 } 692 else 693 viewport()->unsetCursor(); 694 emitMouseStateChanged(); 695 vboxProblem().remindAboutMouseIntegration(m_bIsMouseAbsolute); 696 } 697 if (bNeedsHostCursor) 698 setMouseIntegrationLocked(false); 699 else 700 setMouseIntegrationLocked(true); 701 } 702 703 void UIMachineView::sltKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock) 704 { 705 if (bNumLock != m_numLock) 706 m_uNumLockAdaptionCnt = 2; 707 if (bCapsLock != m_capsLock) 708 m_uCapsLockAdaptionCnt = 2; 709 m_numLock = bNumLock; 710 m_capsLock = bCapsLock; 711 m_scrollLock = bScrollLock; 712 } 713 714 void UIMachineView::sltStateChange(KMachineState state) 715 { 716 switch (state) 717 { 718 case KMachineState_Paused: 719 case KMachineState_TeleportingPausedVM: 720 { 721 if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer && 722 (state != KMachineState_TeleportingPausedVM || m_machineState != KMachineState_Teleporting)) 723 { 724 /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */ 725 QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32); 726 CDisplay dsp = m_console.GetDisplay(); 727 dsp.TakeScreenShot(shot.bits(), shot.width(), shot.height()); 728 /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered 729 * after the machine execution was resumed. It's not fatal: */ 730 if (dsp.isOk()) 731 { 732 dimImage(shot); 733 m_pauseShot = QPixmap::fromImage(shot); 734 /* Fully repaint to pick up m_pauseShot: */ 735 repaint(); 736 } 737 } 738 } 739 case KMachineState_Stuck: 740 { 741 /* Reuse the focus event handler to uncapture everything: */ 742 if (hasFocus()) 743 focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */); 744 break; 745 } 746 case KMachineState_Running: 747 { 748 if (m_machineState == KMachineState_Paused || m_machineState == KMachineState_TeleportingPausedVM) 749 { 750 if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer) 751 { 752 /* Reset the pixmap to free memory: */ 753 m_pauseShot = QPixmap(); 754 /* Ask for full guest display update (it will also update 755 * the viewport through IFramebuffer::NotifyUpdate): */ 756 CDisplay dsp = m_console.GetDisplay(); 757 dsp.InvalidateAndUpdate(); 758 } 759 } 760 /* Reuse the focus event handler to capture input: */ 761 if (hasFocus()) 762 focusEvent(true /* aHasFocus */); 763 break; 764 } 765 default: 766 break; 767 } 768 769 m_machineState = state; 770 } 771 772 void UIMachineView::sltAdditionsStateChange() 773 { 774 CGuest guest = console().GetGuest(); 775 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics(); 776 777 #if 0 // TODO: Do we need this? 778 if (!mDoResize && !isGuestSupportsGraphics() && fIsGuestSupportsGraphics && 779 (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen())) 780 mDoResize = true; 781 #endif 782 m_bIsGuestSupportsGraphics = fIsGuestSupportsGraphics; 783 784 maybeRestrictMinimumSize(); 785 786 #if 0 // TODO: Do we need this? 787 /* This will only be acted upon if mDoResize is true: */ 788 doResizeHint(); 789 #endif 605 790 } 606 791 … … 639 824 #endif 640 825 641 bool UIMachineView::event(QEvent *e) 642 { 643 //if (m_bIsAttached) 644 { 645 switch (e->type()) 646 { 647 case QEvent::FocusIn: 648 { 649 if (isRunning()) 650 focusEvent (true); 651 break; 652 } 653 case QEvent::FocusOut: 654 { 655 if (isRunning()) 656 focusEvent (false); 826 bool UIMachineView::event(QEvent *pEvent) 827 { 828 switch (pEvent->type()) 829 { 830 case QEvent::FocusIn: 831 { 832 if (isRunning()) 833 focusEvent(true); 834 break; 835 } 836 case QEvent::FocusOut: 837 { 838 if (isRunning()) 839 focusEvent(false); 840 else 841 { 842 /* Release the host key and all other pressed keys too even when paused (otherwise, we will get stuck 843 * keys in the guest when doing sendChangedKeyStates() on resume because key presses were already 844 * recorded in m_pressedKeys but key releases will most likely not reach us but the new focus window instead): */ 845 releaseAllPressedKeys(true /* fReleaseHostKey */); 846 } 847 break; 848 } 849 850 case VBoxDefs::ResizeEventType: 851 { 852 /* Some situations require initial VGA Resize Request 853 * to be ignored at all, leaving previous framebuffer, 854 * machine view and machine window sizes preserved: */ 855 if (m_bIsGuestResizeIgnored) 856 return true; 857 858 bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored; 859 m_bIsMachineWindowResizeIgnored = true; 860 861 UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent); 862 863 /* Store the new size to prevent unwanted resize hints being sent back. */ 864 storeConsoleSize(pResizeEvent->width(), pResizeEvent->height()); 865 866 /* Unfortunately restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen widgets are present. 867 * This is the case on linux with SDL. As workaround we save/restore the arrow cursor manually. 868 * See http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry for details. 869 * Moreover the current cursor, which could be set by the guest, should be restored after resize: */ 870 QCursor cursor; 871 if (shouldHideHostPointer()) 872 cursor = QCursor(Qt::BlankCursor); 873 else 874 cursor = viewport()->cursor(); 875 m_pFrameBuffer->resizeEvent(pResizeEvent); 876 viewport()->setCursor(cursor); 877 878 #ifdef Q_WS_MAC 879 mDockIconPreview->setOriginalSize(pResizeEvent->width(), pResizeEvent->height()); 880 #endif /* Q_WS_MAC */ 881 882 /* This event appears in case of guest video was changed for somehow even without video resolution change. 883 * In this last case the host VM window will not be resized according this event and the host mouse cursor 884 * which was unset to default here will not be hidden in capture state. So it is necessary to perform 885 * updateMouseClipping() for the guest resize event if the mouse cursor was captured: */ 886 if (m_bIsMouseCaptured) 887 updateMouseClipping(); 888 889 /* Apply maximum size restriction: */ 890 setMaximumSize(sizeHint()); 891 892 /* May be we have to restrict minimum size? */ 893 maybeRestrictMinimumSize(); 894 895 /* Resize the guest canvas: */ 896 if (!m_bIsFrameBufferResizeIgnored) 897 resize(pResizeEvent->width(), pResizeEvent->height()); 898 updateSliders(); 899 900 /* Let our toplevel widget calculate its sizeHint properly. */ 901 #ifdef Q_WS_X11 902 /* We use processEvents rather than sendPostedEvents & set the time out value to max cause on X11 otherwise 903 * the layout isn't calculated correctly. Dosn't find the bug in Qt, but this could be triggered through 904 * the async nature of the X11 window event system. */ 905 QCoreApplication::processEvents(QEventLoop::AllEvents, INT_MAX); 906 #else /* Q_WS_X11 */ 907 QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest); 908 #endif /* Q_WS_X11 */ 909 910 if (!m_bIsFrameBufferResizeIgnored) 911 normalizeGeometry(true /* adjustPosition */); 912 913 /* Report to the VM thread that we finished resizing */ 914 m_console.GetDisplay().ResizeCompleted(0); 915 916 m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize; 917 918 /* Make sure that all posted signals are processed: */ 919 qApp->processEvents(); 920 921 /* Emit a signal about guest was resized: */ 922 emit resizeHintDone(); 923 924 /* We also recalculate the desktop geometry if this is determined 925 * automatically. In fact, we only need this on the first resize, 926 * but it is done every time to keep the code simpler. */ 927 calculateDesktopGeometry(); 928 929 /* Enable frame-buffer resize watching only now: */ 930 if (m_bIsFrameBufferResizeIgnored) 931 m_bIsFrameBufferResizeIgnored = false; 932 933 return true; 934 } 935 936 /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(): */ 937 case VBoxDefs::RepaintEventType: 938 { 939 UIRepaintEvent *pPaintEvent = static_cast<UIRepaintEvent*>(pEvent); 940 viewport()->repaint(pPaintEvent->x() - contentsX(), pPaintEvent->y() - contentsY(), 941 pPaintEvent->width(), pPaintEvent->height()); 942 /* m_console.GetDisplay().UpdateCompleted(); - the event was acked already */ 943 return true; 944 } 945 946 #ifdef VBOX_WITH_VIDEOHWACCEL 947 case VBoxDefs::VHWACommandProcessType: 948 { 949 m_pFrameBuffer->doProcessVHWACommand(pEvent); 950 return true; 951 } 952 #endif 953 954 #if 0 // TODO: Move that to seamless mode event hadler! 955 case VBoxDefs::SetRegionEventType: 956 { 957 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) pEvent; 958 if (machineWindowWrapper()->isTrueSeamless() && sre->region() != mLastVisibleRegion) 959 { 960 mLastVisibleRegion = sre->region(); 961 machineWindowWrapper()->setMask (sre->region()); 962 } 963 else if (!mLastVisibleRegion.isEmpty() && !machineWindowWrapper()->isTrueSeamless()) 964 mLastVisibleRegion = QRegion(); 965 return true; 966 } 967 #endif 968 969 #if 0 // TODO: Move that to specific event handler! 970 case VBoxDefs::ActivateMenuEventType: 971 { 972 ActivateMenuEvent *pMenuEvent = static_cast<ActivateMenuEvent*>(pEvent); 973 pMenuEvent->action()->trigger(); 974 975 /* The main window and its children can be destroyed at this point (if, for example, the activated menu 976 * item closes the main window). Detect this situation to prevent calls to destroyed widgets: */ 977 QWidgetList list = QApplication::topLevelWidgets(); 978 bool destroyed = list.indexOf(machineWindowWrapper()->machineWindow()) < 0; 979 if (!destroyed && machineWindowWrapper()->machineWindow()->statusBar()) 980 machineWindowWrapper()->machineWindow()->statusBar()->clearMessage(); 981 982 return true; 983 } 984 #endif 985 986 case QEvent::KeyPress: 987 case QEvent::KeyRelease: 988 { 989 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent); 990 991 #ifdef Q_WS_PM 992 // TODO: that a temporary solution to send Alt+Tab and friends to the guest. 993 // The proper solution is to write a keyboard driver that will steal these combos from the host 994 // (it's impossible to do so using hooks on OS/2): 995 996 if (m_bIsHostkeyPressed) 997 { 998 bool pressed = pEvent->type() == QEvent::KeyPress; 999 CKeyboard keyboard = m_console.GetKeyboard(); 1000 1001 /* Whether the host key is Shift so that it will modify the hot key values? 1002 * Note that we don't distinguish between left and right shift here (too much hassle): */ 1003 const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT || 1004 m_globalSettings.hostKey() == VK_LSHIFT) && 1005 (pKeyEvent->state() & Qt::ShiftModifier); 1006 /* define hot keys according to the Shift state */ 1007 const int kAltTab = kShift ? Qt::Key_Exclam : Qt::Key_1; 1008 const int kAltShiftTab = kShift ? Qt::Key_At : Qt::Key_2; 1009 const int kCtrlEsc = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft; 1010 1011 /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */ 1012 if (pKeyEvent->key() == kAltTab || pKeyEvent->key() == kAltShiftTab) 1013 { 1014 if (pressed) 1015 { 1016 /* Send the Alt press to the guest */ 1017 if (!(m_pressedKeysCopy[0x38] & IsKeyPressed)) 1018 { 1019 /* Store the press in *Copy to have it automatically 1020 * released when the Host key is released: */ 1021 m_pressedKeysCopy[0x38] |= IsKeyPressed; 1022 keyboard.PutScancode(0x38); 1023 } 1024 1025 /* Make sure Shift is pressed if it's Key_2 and released if it's Key_1: */ 1026 if (pKeyEvent->key() == kAltTab && 1027 (m_pressedKeysCopy[0x2A] & IsKeyPressed)) 1028 { 1029 m_pressedKeysCopy[0x2A] &= ~IsKeyPressed; 1030 keyboard.PutScancode(0xAA); 1031 } 1032 else 1033 if (pKeyEvent->key() == kAltShiftTab && 1034 !(m_pressedKeysCopy[0x2A] & IsKeyPressed)) 1035 { 1036 m_pressedKeysCopy[0x2A] |= IsKeyPressed; 1037 keyboard.PutScancode(0x2A); 1038 } 1039 } 1040 1041 keyboard.PutScancode(pressed ? 0x0F : 0x8F); 1042 1043 pKeyEvent->accept(); 1044 return true; 1045 } 1046 1047 /* Simulate Ctrl+Esc on Host+Tilde */ 1048 if (pKeyEvent->key() == kCtrlEsc) 1049 { 1050 /* Send the Ctrl press to the guest */ 1051 if (pressed && !(m_pressedKeysCopy[0x1d] & IsKeyPressed)) 1052 { 1053 /* store the press in *Copy to have it automatically 1054 * released when the Host key is released */ 1055 m_pressedKeysCopy[0x1d] |= IsKeyPressed; 1056 keyboard.PutScancode(0x1d); 1057 } 1058 1059 keyboard.PutScancode(pressed ? 0x01 : 0x81); 1060 1061 pKeyEvent->accept(); 1062 return true; 1063 } 1064 } 1065 #endif /* Q_WS_PM */ 1066 1067 if (m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyPress) 1068 { 1069 if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F12) 1070 { 1071 QVector <LONG> combo(6); 1072 combo[0] = 0x1d; /* Ctrl down */ 1073 combo[1] = 0x38; /* Alt down */ 1074 combo[4] = 0xb8; /* Alt up */ 1075 combo[5] = 0x9d; /* Ctrl up */ 1076 if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F10) 1077 { 1078 combo[2] = 0x3b + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 down */ 1079 combo[3] = 0xbb + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 up */ 1080 } 1081 /* some scan slice */ 1082 else if (pKeyEvent->key() >= Qt::Key_F11 && pKeyEvent->key() <= Qt::Key_F12) 1083 { 1084 combo[2] = 0x57 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 down */ 1085 combo[3] = 0xd7 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 up */ 1086 } 1087 else 1088 Assert(0); 1089 1090 CKeyboard keyboard = m_console.GetKeyboard(); 1091 keyboard.PutScancodes(combo); 1092 } 1093 1094 #if 0 // TODO: Divide tha code to specific parts and move it there: 1095 if (pKeyEvent->key() == Qt::Key_Home) 1096 { 1097 /* Activate the main menu */ 1098 if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()) 1099 machineWindowWrapper()->popupMainMenu (m_bIsMouseCaptured); 1100 else 1101 { 1102 /* In Qt4 it is not enough to just set the focus to menu-bar. 1103 * So to get the menu-bar we have to send Qt::Key_Alt press/release events directly: */ 1104 QKeyEvent e1(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier); 1105 QKeyEvent e2(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier); 1106 QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e1); 1107 QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e2); 1108 } 1109 } 657 1110 else 658 1111 { 659 /* release the host key and all other pressed keys too even 660 * when paused (otherwise, we will get stuck keys in the 661 * guest when doing sendChangedKeyStates() on resume because 662 * key presses were already recorded in mPressedKeys but key 663 * releases will most likely not reach us but the new focus 664 * window instead). */ 665 releaseAllPressedKeys (true /* aReleaseHostKey */); 1112 /* Process hot keys not processed in keyEvent() (as in case of non-alphanumeric keys): */ 1113 processHotKey(QKeySequence (pKeyEvent->key()), machineWindowWrapper()->menuBar()->actions()); 666 1114 } 667 break; 668 } 669 670 case VBoxDefs::ResizeEventType: 671 { 672 /* Some situations require initial VGA Resize Request 673 * to be ignored at all, leaving previous framebuffer, 674 * console widget and vm window size preserved. */ 675 if (m_bIsGuestResizeIgnored) 676 return true; 677 678 bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored; 679 m_bIsMachineWindowResizeIgnored = true; 680 681 UIResizeEvent *re = (UIResizeEvent *) e; 682 LogFlow (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n", 683 re->width(), re->height(), re->bitsPerPixel())); 684 #ifdef DEBUG_michael 685 LogRel (("Resize event from guest: %d x %d x %d bpp\n", 686 re->width(), re->height(), re->bitsPerPixel())); 687 #endif 688 689 /* Store the new size to prevent unwanted resize hints being 690 * sent back. */ 691 storeConsoleSize(re->width(), re->height()); 692 /* do frame buffer dependent resize */ 693 694 /* restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen 695 * widgets are present. This is the case on linux with SDL. As 696 * workaround we save/restore the arrow cursor manually. See 697 * http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry 698 * for details. 699 * 700 * Moreover the current cursor, which could be set by the guest, 701 * should be restored after resize. 702 */ 703 QCursor cursor; 704 if (shouldHideHostPointer()) 705 cursor = QCursor (Qt::BlankCursor); 706 else 707 cursor = viewport()->cursor(); 708 mFrameBuf->resizeEvent (re); 709 viewport()->setCursor (cursor); 1115 #endif 1116 } 1117 else if (!m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyRelease) 1118 { 1119 /* Show a possible warning on key release which seems to be more expected by the end user: */ 1120 if (machineWindowWrapper()->machineLogic()->isPaused()) 1121 { 1122 /* Iif the reminder is disabled we pass the event to Qt to enable normal 1123 * keyboard functionality (for example, menu access with Alt+Letter): */ 1124 if (!vboxProblem().remindAboutPausedVMInput()) 1125 break; 1126 } 1127 } 1128 1129 pKeyEvent->accept(); 1130 return true; 1131 } 710 1132 711 1133 #ifdef Q_WS_MAC 712 mDockIconPreview->setOriginalSize (re->width(), re->height()); 713 #endif /* Q_WS_MAC */ 714 715 /* This event appears in case of guest video was changed 716 * for somehow even without video resolution change. 717 * In this last case the host VM window will not be resized 718 * according this event and the host mouse cursor which was 719 * unset to default here will not be hidden in capture state. 720 * So it is necessary to perform updateMouseClipping() for 721 * the guest resize event if the mouse cursor was captured. */ 722 if (m_bIsMouseCaptured) 723 updateMouseClipping(); 724 725 /* apply maximum size restriction */ 726 setMaximumSize (sizeHint()); 727 728 maybeRestrictMinimumSize(); 729 730 /* resize the guest canvas */ 731 if (!m_bIsFrameBufferResizeIgnored) 732 resize (re->width(), re->height()); 733 updateSliders(); 734 /* Let our toplevel widget calculate its sizeHint properly. */ 735 #ifdef Q_WS_X11 736 /* We use processEvents rather than sendPostedEvents & set the 737 * time out value to max cause on X11 otherwise the layout 738 * isn't calculated correctly. Dosn't find the bug in Qt, but 739 * this could be triggered through the async nature of the X11 740 * window event system. */ 741 QCoreApplication::processEvents (QEventLoop::AllEvents, INT_MAX); 742 #else /* Q_WS_X11 */ 743 QCoreApplication::sendPostedEvents (0, QEvent::LayoutRequest); 744 #endif /* Q_WS_X11 */ 745 746 if (!m_bIsFrameBufferResizeIgnored) 747 normalizeGeometry (true /* adjustPosition */); 748 749 /* report to the VM thread that we finished resizing */ 750 m_console.GetDisplay().ResizeCompleted (0); 751 752 m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize; 753 754 /* update geometry after entering fullscreen | seamless */ 755 // if (machineWindowWrapper()->isTrueFullscreen() || machineWindowWrapper()->isTrueSeamless()) TODO check that! 756 updateGeometry(); 757 758 /* make sure that all posted signals are processed */ 759 qApp->processEvents(); 760 761 /* emit a signal about guest was resized */ 762 emit resizeHintDone(); 763 764 /* We also recalculate the desktop geometry if this is determined 765 * automatically. In fact, we only need this on the first resize, 766 * but it is done every time to keep the code simpler. */ 767 calculateDesktopGeometry(); 768 769 /* Enable frame-buffer resize watching. */ 770 if (m_bIsFrameBufferResizeIgnored) 771 { 772 m_bIsFrameBufferResizeIgnored = false; 773 } 774 775 // machineWindowWrapper()->onDisplayResize (re->width(), re->height()); TODO check that! 776 777 return true; 778 } 779 780 /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(). */ 781 case VBoxDefs::RepaintEventType: 782 { 783 UIRepaintEvent *re = (UIRepaintEvent *) e; 784 viewport()->repaint (re->x() - contentsX(), 785 re->y() - contentsY(), 786 re->width(), re->height()); 787 /* m_console.GetDisplay().UpdateCompleted(); - the event was acked already */ 788 return true; 789 } 790 791 #ifdef VBOX_WITH_VIDEOHWACCEL 792 case VBoxDefs::VHWACommandProcessType: 793 { 794 mFrameBuf->doProcessVHWACommand(e); 795 return true; 796 } 797 #endif 798 799 #if 0 800 // TODO check that! 801 case VBoxDefs::SetRegionEventType: 802 { 803 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e; 804 if (machineWindowWrapper()->isTrueSeamless() && sre->region() != mLastVisibleRegion) 805 { 806 mLastVisibleRegion = sre->region(); 807 machineWindowWrapper()->setMask (sre->region()); 808 } 809 else if (!mLastVisibleRegion.isEmpty() && !machineWindowWrapper()->isTrueSeamless()) 810 mLastVisibleRegion = QRegion(); 811 return true; 812 } 813 #endif 814 815 #if 0 816 case VBoxDefs::ActivateMenuEventType: 817 { 818 ActivateMenuEvent *ame = (ActivateMenuEvent *) e; 819 ame->action()->trigger(); 820 821 /* 822 * The main window and its children can be destroyed at this 823 * point (if, for example, the activated menu item closes the 824 * main window). Detect this situation to prevent calls to 825 * destroyed widgets. 826 */ 827 QWidgetList list = QApplication::topLevelWidgets(); 828 bool destroyed = list.indexOf (machineWindowWrapper()->machineWindow()) < 0; 829 if (!destroyed && machineWindowWrapper()->machineWindow()->statusBar()) 830 machineWindowWrapper()->machineWindow()->statusBar()->clearMessage(); 831 832 return true; 833 } 834 #endif 835 836 case QEvent::KeyPress: 837 case QEvent::KeyRelease: 838 { 839 QKeyEvent *ke = (QKeyEvent *) e; 840 841 #ifdef Q_WS_PM 842 /// @todo temporary solution to send Alt+Tab and friends to 843 // the guest. The proper solution is to write a keyboard 844 // driver that will steal these combos from the host (it's 845 // impossible to do so using hooks on OS/2). 846 847 if (m_bIsHostkeyPressed) 848 { 849 bool pressed = e->type() == QEvent::KeyPress; 850 CKeyboard keyboard = m_console.GetKeyboard(); 851 852 /* whether the host key is Shift so that it will modify 853 * the hot key values? Note that we don't distinguish 854 * between left and right shift here (too much hassle) */ 855 const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT || 856 m_globalSettings.hostKey() == VK_LSHIFT) && 857 (ke->state() & Qt::ShiftModifier); 858 /* define hot keys according to the Shift state */ 859 const int kAltTab = kShift ? Qt::Key_Exclam : Qt::Key_1; 860 const int kAltShiftTab = kShift ? Qt::Key_At : Qt::Key_2; 861 const int kCtrlEsc = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft; 862 863 /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */ 864 if (ke->key() == kAltTab || ke->key() == kAltShiftTab) 865 { 866 if (pressed) 867 { 868 /* Send the Alt press to the guest */ 869 if (!(mPressedKeysCopy [0x38] & IsKeyPressed)) 870 { 871 /* store the press in *Copy to have it automatically 872 * released when the Host key is released */ 873 mPressedKeysCopy [0x38] |= IsKeyPressed; 874 keyboard.PutScancode (0x38); 875 } 876 877 /* Make sure Shift is pressed if it's Key_2 and released 878 * if it's Key_1 */ 879 if (ke->key() == kAltTab && 880 (mPressedKeysCopy [0x2A] & IsKeyPressed)) 881 { 882 mPressedKeysCopy [0x2A] &= ~IsKeyPressed; 883 keyboard.PutScancode (0xAA); 884 } 885 else 886 if (ke->key() == kAltShiftTab && 887 !(mPressedKeysCopy [0x2A] & IsKeyPressed)) 888 { 889 mPressedKeysCopy [0x2A] |= IsKeyPressed; 890 keyboard.PutScancode (0x2A); 891 } 892 } 893 894 keyboard.PutScancode (pressed ? 0x0F : 0x8F); 895 896 ke->accept(); 897 return true; 898 } 899 900 /* Simulate Ctrl+Esc on Host+Tilde */ 901 if (ke->key() == kCtrlEsc) 902 { 903 /* Send the Ctrl press to the guest */ 904 if (pressed && !(mPressedKeysCopy [0x1d] & IsKeyPressed)) 905 { 906 /* store the press in *Copy to have it automatically 907 * released when the Host key is released */ 908 mPressedKeysCopy [0x1d] |= IsKeyPressed; 909 keyboard.PutScancode (0x1d); 910 } 911 912 keyboard.PutScancode (pressed ? 0x01 : 0x81); 913 914 ke->accept(); 915 return true; 916 } 917 } 918 919 /* fall through to normal processing */ 920 921 #endif /* Q_WS_PM */ 922 923 if (m_bIsHostkeyPressed && e->type() == QEvent::KeyPress) 924 { 925 if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12) 926 { 927 QVector <LONG> combo (6); 928 combo [0] = 0x1d; /* Ctrl down */ 929 combo [1] = 0x38; /* Alt down */ 930 combo [4] = 0xb8; /* Alt up */ 931 combo [5] = 0x9d; /* Ctrl up */ 932 if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F10) 933 { 934 combo [2] = 0x3b + (ke->key() - Qt::Key_F1); /* F1-F10 down */ 935 combo [3] = 0xbb + (ke->key() - Qt::Key_F1); /* F1-F10 up */ 936 } 937 /* some scan slice */ 938 else if (ke->key() >= Qt::Key_F11 && ke->key() <= Qt::Key_F12) 939 { 940 combo [2] = 0x57 + (ke->key() - Qt::Key_F11); /* F11-F12 down */ 941 combo [3] = 0xd7 + (ke->key() - Qt::Key_F11); /* F11-F12 up */ 942 } 943 else 944 Assert (0); 945 946 CKeyboard keyboard = m_console.GetKeyboard(); 947 keyboard.PutScancodes (combo); 948 } 949 #if 0 950 // TODO check that! 951 else if (ke->key() == Qt::Key_Home) 952 { 953 /* Activate the main menu */ 954 if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()) 955 machineWindowWrapper()->popupMainMenu (m_bIsMouseCaptured); 956 else 957 { 958 /* In Qt4 it is not enough to just set the focus to 959 * menu-bar. So to get the menu-bar we have to send 960 * Qt::Key_Alt press/release events directly. */ 961 QKeyEvent e1 (QEvent::KeyPress, Qt::Key_Alt, 962 Qt::NoModifier); 963 QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt, 964 Qt::NoModifier); 965 QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e1); 966 QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e2); 967 } 968 } 969 else 970 { 971 /* process hot keys not processed in keyEvent() 972 * (as in case of non-alphanumeric keys) */ 973 processHotKey (QKeySequence (ke->key()), 974 machineWindowWrapper()->menuBar()->actions()); 975 } 976 #endif 977 } 978 else if (!m_bIsHostkeyPressed && e->type() == QEvent::KeyRelease) 979 { 980 /* Show a possible warning on key release which seems to 981 * be more expected by the end user */ 982 983 if (machineWindowWrapper()->machineLogic()->isPaused()) 984 { 985 /* if the reminder is disabled we pass the event to 986 * Qt to enable normal keyboard functionality 987 * (for example, menu access with Alt+Letter) */ 988 if (!vboxProblem().remindAboutPausedVMInput()) 989 break; 990 } 991 } 992 993 ke->accept(); 994 return true; 995 } 996 997 #ifdef Q_WS_MAC 998 /* posted OnShowWindow */ 999 case VBoxDefs::ShowWindowEventType: 1000 { 1001 /* 1002 * Dunno what Qt3 thinks a window that has minimized to the dock 1003 * should be - it is not hidden, neither is it minimized. OTOH it is 1004 * marked shown and visible, but not activated. This latter isn't of 1005 * much help though, since at this point nothing is marked activated. 1006 * I might have overlooked something, but I'm buggered what if I know 1007 * what. So, I'll just always show & activate the stupid window to 1008 * make it get out of the dock when the user wishes to show a VM. 1009 */ 1010 window()->show(); 1011 window()->activateWindow(); 1012 return true; 1013 } 1014 #endif 1015 default: 1016 break; 1017 } 1018 } 1019 1020 return QAbstractScrollArea::event (e); 1021 } 1022 1023 bool UIMachineView::eventFilter(QObject *watched, QEvent *e) 1024 { 1025 if (watched == viewport()) 1026 { 1027 switch (e->type()) 1134 /* posted OnShowWindow */ 1135 case VBoxDefs::ShowWindowEventType: 1136 { 1137 /* Dunno what Qt3 thinks a window that has minimized to the dock should be - it is not hidden, 1138 * neither is it minimized. OTOH it is marked shown and visible, but not activated. 1139 * This latter isn't of much help though, since at this point nothing is marked activated. 1140 * I might have overlooked something, but I'm buggered what if I know what. So, I'll just always 1141 * show & activate the stupid window to make it get out of the dock when the user wishes to show a VM: */ 1142 window()->show(); 1143 window()->activateWindow(); 1144 return true; 1145 } 1146 #endif 1147 1148 default: 1149 break; 1150 } 1151 1152 return QAbstractScrollArea::event(pEvent); 1153 } 1154 1155 bool UIMachineView::eventFilter(QObject *pWatched, QEvent *pEvent) 1156 { 1157 if (pWatched == viewport()) 1158 { 1159 switch (pEvent->type()) 1028 1160 { 1029 1161 case QEvent::MouseMove: … … 1032 1164 case QEvent::MouseButtonRelease: 1033 1165 { 1034 QMouseEvent * me = (QMouseEvent *) e;1166 QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent); 1035 1167 m_iLastMouseWheelDelta = 0; 1036 if (mouseEvent (me->type(), me->pos(), me->globalPos(), 1037 me->buttons(), me->modifiers(), 1038 0, Qt::Horizontal)) 1039 return true; /* stop further event handling */ 1168 if (mouseEvent(pMouseEvent->type(), pMouseEvent->pos(), pMouseEvent->globalPos(), 1169 pMouseEvent->buttons(), pMouseEvent->modifiers(), 0, Qt::Horizontal)) 1170 return true; 1040 1171 break; 1041 1172 } 1042 1173 case QEvent::Wheel: 1043 1174 { 1044 QWheelEvent *we = (QWheelEvent *) e; 1045 /* There are pointing devices which send smaller values for the 1046 * delta than 120. Here we sum them up until we are greater 1047 * than 120. This allows to have finer control over the speed 1048 * acceleration & enables such devices to send a valid wheel 1049 * event to our guest mouse device at all. */ 1175 QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent); 1176 /* There are pointing devices which send smaller values for the delta than 120. 1177 * Here we sum them up until we are greater than 120. This allows to have finer control 1178 * over the speed acceleration & enables such devices to send a valid wheel event to our 1179 * guest mouse device at all: */ 1050 1180 int iDelta = 0; 1051 m_iLastMouseWheelDelta += we->delta();1181 m_iLastMouseWheelDelta += pWheelEvent->delta(); 1052 1182 if (qAbs(m_iLastMouseWheelDelta) >= 120) 1053 1183 { … … 1055 1185 m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120; 1056 1186 } 1057 if (mouseEvent (we->type(), we->pos(), we->globalPos(),1187 if (mouseEvent(pWheelEvent->type(), pWheelEvent->pos(), pWheelEvent->globalPos(), 1058 1188 #ifdef QT_MAC_USE_COCOA 1059 /* Qt Cocoa is buggy. It always reports a left 1060 * button pressed when the mouse wheel event 1061 * occurs. A workaround is to ask the 1062 * application which buttons are pressed 1063 * currently. */ 1189 /* Qt Cocoa is buggy. It always reports a left button pressed when the 1190 * mouse wheel event occurs. A workaround is to ask the application which 1191 * buttons are pressed currently: */ 1064 1192 QApplication::mouseButtons(), 1065 1193 #else /* QT_MAC_USE_COCOA */ 1066 we->buttons(),1194 pWheelEvent->buttons(), 1067 1195 #endif /* QT_MAC_USE_COCOA */ 1068 we->modifiers(),1069 iDelta, we->orientation()))1070 return true; /* stop further event handling */1196 pWheelEvent->modifiers(), 1197 iDelta, pWheelEvent->orientation())) 1198 return true; 1071 1199 break; 1072 1200 } … … 1074 1202 case QEvent::Leave: 1075 1203 { 1076 /* Enable mouse event compression if we leave the VM view. This 1077 is necessary for having smooth resizing of the VM/other 1078 windows. */ 1079 setMouseCoalescingEnabled (true); 1204 /* Enable mouse event compression if we leave the VM view. This is necessary for 1205 * having smooth resizing of the VM/other windows: */ 1206 setMouseCoalescingEnabled(true); 1080 1207 break; 1081 1208 } 1082 1209 case QEvent::Enter: 1083 1210 { 1084 /* Disable mouse event compression if we enter the VM view. So 1085 all mouse events are registered in the VM. Only do this if 1086 the keyboard/mouse is grabbed (this is when we have a valid 1087 event handler). */ 1211 /* Disable mouse event compression if we enter the VM view. So all mouse events are 1212 * registered in the VM. Only do this if the keyboard/mouse is grabbed (this is when 1213 * we have a valid event handler): */ 1088 1214 setMouseCoalescingEnabled (false); 1089 1215 break; … … 1095 1221 updateMouseClipping(); 1096 1222 #ifdef VBOX_WITH_VIDEOHWACCEL 1097 if (m FrameBuf)1223 if (m_pFrameBuffer) 1098 1224 { 1099 m FrameBuf->viewportResized((QResizeEvent*)e);1225 m_pFrameBuffer->viewportResized(static_cast<QResizeEvent*>(pEvent)); 1100 1226 } 1101 1227 #endif … … 1106 1232 } 1107 1233 } 1108 else if (watched == machineWindowWrapper()->machineWindow()) 1109 { 1110 switch (e->type()) 1111 { 1112 #if defined (Q_WS_WIN32) 1113 #if defined (VBOX_GUI_USE_DDRAW) 1114 case QEvent::Move: 1115 { 1116 /* 1117 * notification from our parent that it has moved. We need this 1118 * in order to possibly adjust the direct screen blitting. 1119 */ 1120 if (mFrameBuf) 1121 mFrameBuf->moveEvent ((QMoveEvent *) e); 1234 else if (pWatched == machineWindowWrapper()->machineWindow()) 1235 { 1236 switch (pEvent->type()) 1237 { 1238 #if 0 // TODO Move to normal specific event handler: 1239 case QEvent::Resize: 1240 { 1241 /* Set the "guest needs to resize" hint. This hint is acted upon when (and only when) 1242 * the autoresize property is "true": */ 1243 mDoResize = isGuestSupportsGraphics() || machineWindowWrapper()->isTrueFullscreen(); 1244 if (!m_bIsMachineWindowResizeIgnored && isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled) 1245 QTimer::singleShot(300, this, SLOT(doResizeHint())); 1122 1246 break; 1123 1247 } 1124 1248 #endif 1125 /*1126 * install/uninstall low-level kbd hook on every1127 * activation/deactivation to:1128 * a) avoid excess hook calls when we're not active and1129 * b) be always in front of any other possible hooks1130 */1131 case QEvent::WindowActivate:1132 {1133 gKbdHook = SetWindowsHookEx (WH_KEYBOARD_LL, lowLevelKeyboardProc,1134 GetModuleHandle (NULL), 0);1135 AssertMsg (gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));1136 break;1137 }1138 case QEvent::WindowDeactivate:1139 {1140 if (gKbdHook)1141 {1142 UnhookWindowsHookEx (gKbdHook);1143 gKbdHook = NULL;1144 }1145 break;1146 }1147 #endif /* defined (Q_WS_WIN32) */1148 #if defined (Q_WS_MAC)1149 /*1150 * Install/remove the keyboard event handler.1151 */1152 case QEvent::WindowActivate:1153 darwinGrabKeyboardEvents (true);1154 break;1155 case QEvent::WindowDeactivate:1156 darwinGrabKeyboardEvents (false);1157 break;1158 #endif /* defined (Q_WS_MAC) */1159 #if 01160 // TODO check that!1161 case QEvent::Resize:1162 {1163 /* Set the "guest needs to resize" hint. This hint is acted upon1164 * when (and only when) the autoresize property is "true". */1165 mDoResize = m_bIsGuestSupportsGraphics || machineWindowWrapper()->isTrueFullscreen();1166 if (!m_bIsMachineWindowResizeIgnored &&1167 m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled)1168 QTimer::singleShot (300, this, SLOT (doResizeHint()));1169 break;1170 }1171 #endif1172 1249 case QEvent::WindowStateChange: 1173 1250 { 1174 1251 /* During minimizing and state restoring machineWindowWrapper() gets the focus 1175 1252 * which belongs to console view window, so returning it properly. */ 1176 QWindowStateChangeEvent * ev = static_cast <QWindowStateChangeEvent*> (e);1177 if ( ev->oldState() & Qt::WindowMinimized)1253 QWindowStateChangeEvent *pWindowEvent = static_cast<QWindowStateChangeEvent*>(pEvent); 1254 if (pWindowEvent->oldState() & Qt::WindowMinimized) 1178 1255 { 1179 1256 if (QApplication::focusWidget()) … … 1182 1259 qApp->processEvents(); 1183 1260 } 1184 QTimer::singleShot (0, this, SLOT(setFocus()));1261 QTimer::singleShot(0, this, SLOT(setFocus())); 1185 1262 } 1186 1263 break; 1187 1264 } 1188 1265 #if defined (Q_WS_WIN32) 1266 #if defined (VBOX_GUI_USE_DDRAW) 1267 case QEvent::Move: 1268 { 1269 /* Notification from our parent that it has moved. We need this in order 1270 * to possibly adjust the direct screen blitting: */ 1271 if (m_pFrameBuffer) 1272 m_pFrameBuffer->moveEvent(static_cast<QMoveEvent*>(pEvent)); 1273 break; 1274 } 1275 #endif 1276 /* Install/uninstall low-level kbd hook on every activation/deactivation to: 1277 * a) avoid excess hook calls when we're not active and 1278 * b) be always in front of any other possible hooks */ 1279 case QEvent::WindowActivate: 1280 { 1281 gKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0); 1282 AssertMsg(gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError())); 1283 break; 1284 } 1285 case QEvent::WindowDeactivate: 1286 { 1287 if (gKbdHook) 1288 { 1289 UnhookWindowsHookEx(gKbdHook); 1290 gKbdHook = NULL; 1291 } 1292 break; 1293 } 1294 #endif /* defined (Q_WS_WIN32) */ 1295 #if defined (Q_WS_MAC) 1296 /* Install/remove the keyboard event handler: */ 1297 case QEvent::WindowActivate: 1298 darwinGrabKeyboardEvents(true); 1299 break; 1300 case QEvent::WindowDeactivate: 1301 darwinGrabKeyboardEvents(false); 1302 break; 1303 #endif /* defined (Q_WS_MAC) */ 1189 1304 default: 1190 1305 break; 1191 1306 } 1192 1307 } 1193 #if 0 // TODO check that 1194 else if (watched == machineWindowWrapper()->menuBar()) 1195 { 1196 /* 1197 * sometimes when we press ESC in the menu it brings the 1198 * focus away (Qt bug?) causing no widget to have a focus, 1199 * or holds the focus itself, instead of returning the focus 1200 * to the console window. here we fix this. 1201 */ 1202 switch (e->type()) 1308 #if 0 // TODO Move to normal specific event handler: 1309 else if (pWatched == machineWindowWrapper()->menuBar()) 1310 { 1311 /* Sometimes when we press ESC in the menu it brings the focus away (Qt bug?) 1312 * causing no widget to have a focus, or holds the focus itself, instead of 1313 * returning the focus to the console window. Here we fix this: */ 1314 switch (pEvent->type()) 1203 1315 { 1204 1316 case QEvent::FocusOut: … … 1210 1322 case QEvent::KeyPress: 1211 1323 { 1212 QKeyEvent * ke = (QKeyEvent *) e;1213 if ( ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier))1324 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent); 1325 if (pKeyEvent->key() == Qt::Key_Escape && (pKeyEvent->modifiers() == Qt::NoModifier)) 1214 1326 if (machineWindowWrapper()->menuBar()->hasFocus()) 1215 1327 setFocus(); … … 1220 1332 } 1221 1333 } 1222 #endif 1223 1224 return QAbstractScrollArea::eventFilter (watched, e); 1225 } 1226 1227 #if defined(Q_WS_WIN32) 1228 1229 bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event) 1230 { 1231 /* Sometimes it happens that Win inserts additional events on some key 1232 * press/release. For example, it prepends ALT_GR in German layout with 1233 * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary 1234 * to specially treat ALT_GR to enter additional chars to regular apps). 1235 * These events are definitely unwanted in VM, so filter them out. */ 1236 /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan 1237 * code 0x23a. If this is not passed through then it is impossible to 1238 * cancel CapsLock on a French keyboard. I didn't find any other examples 1239 * of these strange events. Let's hope we are not missing anything else 1240 * of importance! */ 1241 if (hasFocus() && (event.scanCode & ~0xFF)) 1242 { 1243 if (event.vkCode == VK_CAPITAL) 1244 return false; 1245 else 1246 return true; 1247 } 1248 1249 if (!m_bIsKeyboardCaptured) 1250 return false; 1251 1252 /* it's possible that a key has been pressed while the keyboard was not 1253 * captured, but is being released under the capture. Detect this situation 1254 * and return false to let Windows process the message normally and update 1255 * its key state table (to avoid the stuck key effect). */ 1256 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed; 1257 if ((event.flags & 0x80) /* released */ && 1258 ((event.vkCode == m_globalSettings.hostKey() && !hostkey_in_capture) || 1259 (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed)) 1260 return false; 1261 1262 MSG message; 1263 message.hwnd = winId(); 1264 message.message = msg; 1265 message.wParam = event.vkCode; 1266 message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24; 1267 1268 /* Windows sets here the extended bit when the Right Shift key is pressed, 1269 * which is totally wrong. Undo it. */ 1270 if (event.vkCode == VK_RSHIFT) 1271 message.lParam &= ~0x1000000; 1272 1273 /* we suppose here that this hook is always called on the main GUI thread */ 1274 long dummyResult; 1275 return winEvent(&message, &dummyResult); 1276 } 1277 1278 bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */) 1279 { 1280 if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN || 1281 aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP)) 1282 return false; 1283 1284 /* Check for the special flag possibly set at the end of this function */ 1285 if (aMsg->lParam & (0x1 << 25)) 1286 { 1287 aMsg->lParam &= ~(0x1 << 25); 1288 return false; 1289 } 1290 1291 int scan = (aMsg->lParam >> 16) & 0x7F; 1292 /* scancodes 0x80 and 0x00 are ignored */ 1293 if (!scan) 1294 return true; 1295 1296 int vkey = aMsg->wParam; 1297 1298 /* When one of the SHIFT keys is held and one of the cursor movement 1299 * keys is pressed, Windows duplicates SHIFT press/release messages, 1300 * but with the virtual key code set to 0xFF. These virtual keys are also 1301 * sent in some other situations (Pause, PrtScn, etc.). Ignore such 1302 * messages. */ 1303 if (vkey == 0xFF) 1304 return true; 1305 1306 int flags = 0; 1307 if (aMsg->lParam & 0x1000000) 1308 flags |= KeyExtended; 1309 if (!(aMsg->lParam & 0x80000000)) 1310 flags |= KeyPressed; 1311 1312 switch (vkey) 1313 { 1314 case VK_SHIFT: 1315 case VK_CONTROL: 1316 case VK_MENU: 1317 { 1318 /* overcome stupid Win32 modifier key generalization */ 1319 int keyscan = scan; 1320 if (flags & KeyExtended) 1321 keyscan |= 0xE000; 1322 switch (keyscan) 1323 { 1324 case 0x002A: vkey = VK_LSHIFT; break; 1325 case 0x0036: vkey = VK_RSHIFT; break; 1326 case 0x001D: vkey = VK_LCONTROL; break; 1327 case 0xE01D: vkey = VK_RCONTROL; break; 1328 case 0x0038: vkey = VK_LMENU; break; 1329 case 0xE038: vkey = VK_RMENU; break; 1330 } 1331 break; 1332 } 1333 case VK_NUMLOCK: 1334 /* Win32 sets the extended bit for the NumLock key. Reset it. */ 1335 flags &= ~KeyExtended; 1336 break; 1337 case VK_SNAPSHOT: 1338 flags |= KeyPrint; 1339 break; 1340 case VK_PAUSE: 1341 flags |= KeyPause; 1342 break; 1343 } 1344 1345 bool result = keyEvent(vkey, scan, flags); 1346 if (!result && m_bIsKeyboardCaptured) 1347 { 1348 /* keyEvent() returned that it didn't process the message, but since the 1349 * keyboard is captured, we don't want to pass it to Windows. We just want 1350 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 1351 * shortcuts for example). So send it direcltly to the window with the 1352 * special flag in the reserved area of lParam (to avoid recursion). */ 1353 ::SendMessage(aMsg->hwnd, aMsg->message, 1354 aMsg->wParam, aMsg->lParam | (0x1 << 25)); 1355 return true; 1356 } 1357 1358 /* These special keys have to be handled by Windows as well to update the 1359 * internal modifier state and to enable/disable the keyboard LED */ 1360 if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT) 1361 return false; 1362 1363 return result; 1364 } 1365 1366 #elif defined (Q_WS_PM) 1367 1368 bool UIMachineView::pmEvent(QMSG *aMsg) 1369 { 1370 if (aMsg->msg == UM_PREACCEL_CHAR) 1371 { 1372 /* We are inside the input hook 1373 * let the message go through the normal system pipeline. */ 1374 if (!m_bIsKeyboardCaptured) 1375 return false; 1376 } 1377 1378 if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR) 1379 return false; 1380 1381 /* check for the special flag possibly set at the end of this function */ 1382 if (SHORT2FROMMP(aMsg->mp2) & 0x8000) 1383 { 1384 aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000); 1385 return false; 1386 } 1387 1388 USHORT ch = SHORT1FROMMP(aMsg->mp2); 1389 USHORT f = SHORT1FROMMP(aMsg->mp1); 1390 1391 int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1); 1392 if (!scan || scan > 0x7F) 1393 return true; 1394 1395 int vkey = QIHotKeyEdit::virtualKey(aMsg); 1396 1397 int flags = 0; 1398 1399 if ((ch & 0xFF) == 0xE0) 1400 { 1401 flags |= KeyExtended; 1402 scan = ch >> 8; 1403 } 1404 else if (scan == 0x5C && (ch & 0xFF) == '/') 1405 { 1406 /* this is the '/' key on the keypad */ 1407 scan = 0x35; 1408 flags |= KeyExtended; 1409 } 1410 else 1411 { 1412 /* For some keys, the scan code passed in QMSG is a pseudo scan 1413 * code. We replace it with a real hardware scan code, according to 1414 * http://www.computer-engineering.org/ps2keyboard/scancodes1.html. 1415 * Also detect Pause and PrtScn and set flags. */ 1416 switch (vkey) 1417 { 1418 case VK_ENTER: scan = 0x1C; flags |= KeyExtended; break; 1419 case VK_CTRL: scan = 0x1D; flags |= KeyExtended; break; 1420 case VK_ALTGRAF: scan = 0x38; flags |= KeyExtended; break; 1421 case VK_LWIN: scan = 0x5B; flags |= KeyExtended; break; 1422 case VK_RWIN: scan = 0x5C; flags |= KeyExtended; break; 1423 case VK_WINMENU: scan = 0x5D; flags |= KeyExtended; break; 1424 case VK_FORWARD: scan = 0x69; flags |= KeyExtended; break; 1425 case VK_BACKWARD: scan = 0x6A; flags |= KeyExtended; break; 1426 #if 0 1427 /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully 1428 // clear what is more correct 1429 case VK_BREAK: scan = 0x46; flags |= KeyExtended; break; 1430 #else 1431 case VK_BREAK: scan = 0; flags |= KeyPause; break; 1432 #endif 1433 case VK_PAUSE: scan = 0; flags |= KeyPause; break; 1434 case VK_PRINTSCRN: scan = 0; flags |= KeyPrint; break; 1435 default:; 1436 } 1437 } 1438 1439 if (!(f & KC_KEYUP)) 1440 flags |= KeyPressed; 1441 1442 bool result = keyEvent (vkey, scan, flags); 1443 if (!result && m_bIsKeyboardCaptured) 1444 { 1445 /* keyEvent() returned that it didn't process the message, but since the 1446 * keyboard is captured, we don't want to pass it to PM. We just want 1447 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 1448 * shortcuts for example). So send it direcltly to the window with the 1449 * special flag in the reserved area of lParam (to avoid recursion). */ 1450 ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1, 1451 MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000)); 1452 return true; 1453 } 1454 return result; 1455 } 1456 1457 #elif defined(Q_WS_X11) 1458 1459 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg) 1460 { 1461 XEvent *pKeyEvent = (XEvent *) pvArg; 1462 if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode)) 1463 return True; 1464 else 1465 return False; 1466 } 1467 1468 bool UIMachineView::x11Event(XEvent *event) 1469 { 1470 switch (event->type) 1471 { 1472 /* We have to handle XFocusOut right here as this event is not passed 1473 * to UIMachineView::event(). Handling this event is important for 1474 * releasing the keyboard before the screen saver gets active. */ 1475 case XFocusOut: 1476 case XFocusIn: 1477 if (isRunning()) 1478 focusEvent(event->type == XFocusIn); 1479 return false; 1480 case XKeyPress: 1481 case XKeyRelease: 1482 break; 1483 default: 1484 return false; /* pass the event to Qt */ 1485 } 1486 1487 /* Translate the keycode to a PC scan code. */ 1488 unsigned scan = handleXKeyEvent(event); 1489 1490 // scancodes 0x00 (no valid translation) and 0x80 are ignored 1491 if (!scan & 0x7F) 1492 return true; 1493 1494 /* Fix for http://www.virtualbox.org/ticket/1296: 1495 * when X11 sends events for repeated keys, it always inserts an 1496 * XKeyRelease before the XKeyPress. */ 1497 XEvent returnEvent; 1498 if ((event->type == XKeyRelease) && (XCheckIfEvent(event->xkey.display, &returnEvent, 1499 VBoxConsoleViewCompEvent, (XPointer) event) == True)) 1500 { 1501 XPutBackEvent(event->xkey.display, &returnEvent); 1502 /* Discard it, don't pass it to Qt. */ 1503 return true; 1504 } 1505 1506 KeySym ks = ::XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0); 1507 1508 int flags = 0; 1509 if (scan >> 8) 1510 flags |= KeyExtended; 1511 if (event->type == XKeyPress) 1512 flags |= KeyPressed; 1513 1514 /* Remove the extended flag */ 1515 scan &= 0x7F; 1516 1517 switch (ks) 1518 { 1519 case XK_Print: 1520 flags |= KeyPrint; 1521 break; 1522 case XK_Pause: 1523 flags |= KeyPause; 1524 break; 1525 } 1526 1527 return keyEvent(ks, scan, flags); 1528 } 1529 1530 #elif defined (Q_WS_MAC) 1531 1532 bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent) 1533 { 1534 bool ret = false; 1535 UInt32 EventKind = ::GetEventKind(inEvent); 1536 if (EventKind != kEventRawKeyModifiersChanged) 1537 { 1538 /* convert keycode to set 1 scan code. */ 1539 UInt32 keyCode = ~0U; 1540 ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode); 1541 unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode); 1542 if (scanCode) 1543 { 1544 /* calc flags. */ 1545 int flags = 0; 1546 if (EventKind != kEventRawKeyUp) 1547 flags |= KeyPressed; 1548 if (scanCode & VBOXKEY_EXTENDED) 1549 flags |= KeyExtended; 1550 /** @todo KeyPause, KeyPrint. */ 1551 scanCode &= VBOXKEY_SCANCODE_MASK; 1552 1553 /* get the unicode string (if present). */ 1554 AssertCompileSize(wchar_t, 2); 1555 AssertCompileSize(UniChar, 2); 1556 ByteCount cbWritten = 0; 1557 wchar_t ucs[8]; 1558 if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 1559 sizeof(ucs), &cbWritten, &ucs[0]) != 0) 1560 cbWritten = 0; 1561 ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */ 1562 1563 ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL); 1564 } 1565 } 1566 else 1567 { 1568 /* May contain multiple modifier changes, kind of annoying. */ 1569 UInt32 newMask = 0; 1570 ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, 1571 sizeof(newMask), NULL, &newMask); 1572 newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent); 1573 UInt32 changed = newMask ^ mDarwinKeyModifiers; 1574 if (changed) 1575 { 1576 for (UInt32 bit = 0; bit < 32; bit++) 1577 { 1578 if (!(changed & (1 << bit))) 1579 continue; 1580 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit); 1581 if (!scanCode) 1582 continue; 1583 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit); 1584 Assert(keyCode); 1585 1586 if (!(scanCode & VBOXKEY_LOCK)) 1587 { 1588 unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0; 1589 if (scanCode & VBOXKEY_EXTENDED) 1590 flags |= KeyExtended; 1591 scanCode &= VBOXKEY_SCANCODE_MASK; 1592 ret |= keyEvent(keyCode, scanCode & 0xff, flags); 1593 } 1594 else 1595 { 1596 unsigned flags = 0; 1597 if (scanCode & VBOXKEY_EXTENDED) 1598 flags |= KeyExtended; 1599 scanCode &= VBOXKEY_SCANCODE_MASK; 1600 keyEvent(keyCode, scanCode, flags | KeyPressed); 1601 keyEvent(keyCode, scanCode, flags); 1602 } 1603 } 1604 } 1605 1606 mDarwinKeyModifiers = newMask; 1607 1608 /* Always return true here because we'll otherwise getting a Qt event 1609 we don't want and that will only cause the Pause warning to pop up. */ 1610 ret = true; 1611 } 1612 1613 return ret; 1614 } 1615 1616 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab) 1617 { 1618 mKeyboardGrabbed = fGrab; 1619 if (fGrab) 1620 { 1621 /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */ 1622 ::CGSetLocalEventsSuppressionInterval(0.0); 1623 setMouseCoalescingEnabled(false); 1624 1625 /* Register the event callback/hook and grab the keyboard. */ 1626 # ifdef QT_MAC_USE_COCOA 1627 ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */ 1628 UIMachineView::darwinEventHandlerProc, this); 1629 1630 # else /* QT_MAC_USE_COCOA */ 1631 EventTypeSpec eventTypes[6]; 1632 eventTypes[0].eventClass = kEventClassKeyboard; 1633 eventTypes[0].eventKind = kEventRawKeyDown; 1634 eventTypes[1].eventClass = kEventClassKeyboard; 1635 eventTypes[1].eventKind = kEventRawKeyUp; 1636 eventTypes[2].eventClass = kEventClassKeyboard; 1637 eventTypes[2].eventKind = kEventRawKeyRepeat; 1638 eventTypes[3].eventClass = kEventClassKeyboard; 1639 eventTypes[3].eventKind = kEventRawKeyModifiersChanged; 1640 /* For ignorning Command-H and Command-Q which aren't affected by the 1641 * global hotkey stuff (doesn't work well): */ 1642 eventTypes[4].eventClass = kEventClassCommand; 1643 eventTypes[4].eventKind = kEventCommandProcess; 1644 eventTypes[5].eventClass = kEventClassCommand; 1645 eventTypes[5].eventKind = kEventCommandUpdateStatus; 1646 1647 EventHandlerUPP eventHandler = ::NewEventHandlerUPP(UIMachineView::darwinEventHandlerProc); 1648 1649 mDarwinEventHandlerRef = NULL; 1650 ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 1651 this, &mDarwinEventHandlerRef); 1652 ::DisposeEventHandlerUPP(eventHandler); 1653 # endif /* !QT_MAC_USE_COCOA */ 1654 1655 ::DarwinGrabKeyboard (false); 1656 } 1657 else 1658 { 1659 ::DarwinReleaseKeyboard(); 1660 # ifdef QT_MAC_USE_COCOA 1661 ::VBoxCocoaApplication_unsetCallback(UINT32_MAX, /** @todo fix mask */ 1662 UIMachineView::darwinEventHandlerProc, this); 1663 # else /* QT_MAC_USE_COCOA */ 1664 if (mDarwinEventHandlerRef) 1665 { 1666 ::RemoveEventHandler(mDarwinEventHandlerRef); 1667 mDarwinEventHandlerRef = NULL; 1668 } 1669 # endif /* !QT_MAC_USE_COCOA */ 1670 } 1671 } 1672 1673 #endif 1674 1675 #if defined (Q_WS_WIN32) 1676 static HHOOK gKbdHook = NULL; 1677 static UIMachineView *gView = 0; 1678 LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 1679 { 1680 Assert (gView); 1681 if (gView && nCode == HC_ACTION && 1682 gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam)) 1683 return 1; 1684 1685 return CallNextHookEx (NULL, nCode, wParam, lParam); 1686 } 1687 #endif 1688 1689 #if defined (Q_WS_MAC) 1690 # ifdef QT_MAC_USE_COCOA 1691 bool UIMachineView::darwinEventHandlerProc (const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser) 1692 { 1693 UIMachineView *view = (UIMachineView*)pvUser; 1694 EventRef inEvent = (EventRef)pvCarbonEvent; 1695 UInt32 eventClass = ::GetEventClass(inEvent); 1696 1697 /* Check if this is an application key combo. In that case we will not pass 1698 the event to the guest, but let the host process it. */ 1699 if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent)) 1700 return false; 1701 1702 /* All keyboard class events needs to be handled. */ 1703 if (eventClass == kEventClassKeyboard) 1704 { 1705 if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent)) 1706 return true; 1707 } 1708 /* Pass the event along. */ 1709 return false; 1710 } 1711 1712 # else /* QT_MAC_USE_COCOA */ 1713 1714 pascal OSStatus UIMachineView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 1715 { 1716 UIMachineView *view = static_cast<UIMachineView *> (inUserData); 1717 UInt32 eventClass = ::GetEventClass (inEvent); 1718 1719 /* Not sure but this seems an triggered event if the spotlight searchbar is 1720 * displayed. So flag that the host key isn't pressed alone. */ 1721 if (eventClass == 'cgs ' && view->m_bIsHostkeyPressed && ::GetEventKind (inEvent) == 0x15) 1722 view->m_bIsHostkeyAlone = false; 1723 1724 if (eventClass == kEventClassKeyboard) 1725 { 1726 if (view->darwinKeyboardEvent (NULL, inEvent)) 1727 return 0; 1728 } 1729 1730 /* 1731 * Command-H and Command-Q aren't properly disabled yet, and it's still 1732 * possible to use the left command key to invoke them when the keyboard 1733 * is captured. We discard the events these if the keyboard is captured 1734 * as a half measure to prevent unexpected behaviour. However, we don't 1735 * get any key down/up events, so these combinations are dead to the guest... 1736 */ 1737 else if (eventClass == kEventClassCommand) 1738 { 1739 if (view->m_bIsKeyboardCaptured) 1740 return 0; 1741 } 1742 return ::CallNextEventHandler(inHandlerCallRef, inEvent); 1743 } 1744 # endif /* !QT_MAC_USE_COCOA */ 1745 1746 #endif /* Q_WS_MAC */ 1747 1748 void UIMachineView::focusEvent(bool aHasFocus, bool aReleaseHostKey /* = true */) 1749 { 1750 if (aHasFocus) 1751 { 1752 #ifdef RT_OS_WINDOWS 1334 #endif 1335 1336 return QAbstractScrollArea::eventFilter (pWatched, pEvent); 1337 } 1338 1339 void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */) 1340 { 1341 if (fHasFocus) 1342 { 1343 #ifdef Q_WS_WIN32 1753 1344 if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture() && GetAncestor(winId(), GA_ROOT) == GetForegroundWindow()) 1754 1345 #else 1755 1346 if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture()) 1756 #endif /* RT_OS_WINDOWS */1347 #endif 1757 1348 { 1758 1349 captureKbd(true); 1759 1350 } 1760 1351 1761 /* reset the single-time disable capture flag*/1352 /* Reset the single-time disable capture flag: */ 1762 1353 if (m_bIsAutoCaptureDisabled) 1763 1354 m_bIsAutoCaptureDisabled = false; … … 1767 1358 captureMouse(false); 1768 1359 captureKbd(false, false); 1769 releaseAllPressedKeys( aReleaseHostKey);1770 } 1771 } 1772 1773 bool UIMachineView::keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey /* = NULL */)1774 { 1775 const bool isHostKey = aKey == m_globalSettings.hostKey();1360 releaseAllPressedKeys(fReleaseHostKey); 1361 } 1362 } 1363 1364 bool UIMachineView::keyEvent(int iKey, uint8_t uScan, int fFlags, wchar_t *pUniKey /* = NULL */) 1365 { 1366 const bool isHostKey = iKey == m_globalSettings.hostKey(); 1776 1367 1777 1368 LONG buf[16]; … … 1782 1373 if (!isHostKey && !m_bIsHostkeyPressed) 1783 1374 { 1784 if ( aFlags & KeyPrint)1375 if (fFlags & KeyPrint) 1785 1376 { 1786 1377 static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 }; 1787 1378 static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA }; 1788 if ( aFlags & KeyPressed)1379 if (fFlags & KeyPressed) 1789 1380 { 1790 1381 codes = PrintMake; … … 1797 1388 } 1798 1389 } 1799 else if ( aFlags & KeyPause)1800 { 1801 if ( aFlags & KeyPressed)1390 else if (fFlags & KeyPause) 1391 { 1392 if (fFlags & KeyPressed) 1802 1393 { 1803 1394 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 }; … … 1813 1404 else 1814 1405 { 1815 if ( aFlags & KeyPressed)1406 if (fFlags & KeyPressed) 1816 1407 { 1817 1408 /* Check if the guest has the same view on the modifier keys (NumLock, … … 1822 1413 1823 1414 /* Check if it's C-A-D and GUI/PassCAD is not true */ 1824 if (!m PassCAD &&1825 aScan == 0x53 /* Del */ &&1826 ((m PressedKeys[0x38] & IsKeyPressed) /* Alt */ ||1827 (m PressedKeys[0x38] & IsExtKeyPressed)) &&1828 ((m PressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ ||1829 (m PressedKeys[0x1d] & IsExtKeyPressed)))1415 if (!m_fPassCAD && 1416 uScan == 0x53 /* Del */ && 1417 ((m_pressedKeys[0x38] & IsKeyPressed) /* Alt */ || 1418 (m_pressedKeys[0x38] & IsExtKeyPressed)) && 1419 ((m_pressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ || 1420 (m_pressedKeys[0x1d] & IsExtKeyPressed))) 1830 1421 { 1831 1422 /* Use the C-A-D combination as a last resort to get the … … 1836 1427 * that's not possible because we cannot predict what other 1837 1428 * keys will be pressed next when one of C, A, D is held. */ 1838 1839 1429 if (isRunning() && m_bIsKeyboardCaptured) 1840 1430 { … … 1847 1437 } 1848 1438 1849 /* process the scancode and update the table of pressed keys*/1439 /* Process the scancode and update the table of pressed keys: */ 1850 1440 whatPressed = IsKeyPressed; 1851 1441 1852 if ( aFlags & KeyExtended)1442 if (fFlags & KeyExtended) 1853 1443 { 1854 1444 codes[count++] = 0xE0; … … 1856 1446 } 1857 1447 1858 if ( aFlags & KeyPressed)1859 { 1860 codes[count++] = aScan;1861 m PressedKeys[aScan] |= whatPressed;1448 if (fFlags & KeyPressed) 1449 { 1450 codes[count++] = uScan; 1451 m_pressedKeys[uScan] |= whatPressed; 1862 1452 } 1863 1453 else 1864 1454 { 1865 /* if we haven't got this key's press message, we ignore its 1866 * release */ 1867 if (!(mPressedKeys [aScan] & whatPressed)) 1455 /* If we haven't got this key's press message, we ignore its release: */ 1456 if (!(m_pressedKeys[uScan] & whatPressed)) 1868 1457 return true; 1869 codes[count++] = aScan | 0x80;1870 m PressedKeys[aScan] &= ~whatPressed;1458 codes[count++] = uScan | 0x80; 1459 m_pressedKeys[uScan] &= ~whatPressed; 1871 1460 } 1872 1461 1873 1462 if (m_bIsKeyboardCaptured) 1874 m PressedKeys[aScan] |= IsKbdCaptured;1463 m_pressedKeys[uScan] |= IsKbdCaptured; 1875 1464 else 1876 m PressedKeys[aScan] &= ~IsKbdCaptured;1465 m_pressedKeys[uScan] &= ~IsKbdCaptured; 1877 1466 } 1878 1467 } 1879 1468 else 1880 1469 { 1881 /* currently this is used in winLowKeyboardEvent() only*/1882 hostkey_in_capture = m_bIsKeyboardCaptured;1470 /* Currently this is used in winLowKeyboardEvent() only: */ 1471 m_bHostkeyInCapture = m_bIsKeyboardCaptured; 1883 1472 } 1884 1473 … … 1886 1475 int hotkey = 0; 1887 1476 1888 /* process the host key*/1889 if ( aFlags & KeyPressed)1477 /* Process the host key: */ 1478 if (fFlags & KeyPressed) 1890 1479 { 1891 1480 if (isHostKey) … … 1905 1494 if (m_bIsHostkeyAlone) 1906 1495 { 1907 hotkey = aKey;1496 hotkey = iKey; 1908 1497 m_bIsHostkeyAlone = false; 1909 1498 } … … 1987 1576 bool processed = false; 1988 1577 #if defined (Q_WS_WIN32) 1989 NOREF( aUniKey);1990 int n = GetKeyboardLayoutList 1578 NOREF(pUniKey); 1579 int n = GetKeyboardLayoutList(0, NULL); 1991 1580 Assert (n); 1992 HKL *list = new HKL 1993 GetKeyboardLayoutList 1581 HKL *list = new HKL[n]; 1582 GetKeyboardLayoutList(n, list); 1994 1583 for (int i = 0; i < n && !processed; i++) 1995 1584 { 1996 1585 wchar_t ch; 1997 static BYTE keys 1998 if (!ToUnicodeEx (hotkey, 0, keys, &ch, 1, 0, list[i]) == 1)1586 static BYTE keys[256] = {0}; 1587 if (!ToUnicodeEx(hotkey, 0, keys, &ch, 1, 0, list[i]) == 1) 1999 1588 ch = 0; 2000 1589 if (ch) 2001 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 2002 QChar (ch).toUpper().unicode()), 2003 machineWindowWrapper()->menuBar()->actions()); 1590 processed = processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(ch).toUpper().unicode()), 1591 machineWindowWrapper()->menuBar()->actions()); 2004 1592 } 2005 1593 delete[] list; 2006 1594 #elif defined (Q_WS_X11) 2007 NOREF( aUniKey);1595 NOREF(pUniKey); 2008 1596 Display *display = QX11Info::display(); 2009 1597 int keysyms_per_keycode = getKeysymsPerKeycode(); 2010 KeyCode kc = XKeysymToKeycode (display, aKey); 2011 // iterate over the first level (not shifted) keysyms in every group 1598 KeyCode kc = XKeysymToKeycode (display, iKey); 2012 1599 for (int i = 0; i < keysyms_per_keycode && !processed; i += 2) 2013 1600 { 2014 KeySym ks = XKeycodeToKeysym 1601 KeySym ks = XKeycodeToKeysym(display, kc, i); 2015 1602 char ch = 0; 2016 if (!XkbTranslateKeySym 1603 if (!XkbTranslateKeySym(display, &ks, 0, &ch, 1, NULL) == 1) 2017 1604 ch = 0; 2018 1605 if (ch) 2019 { 2020 QChar c = QString::fromLocal8Bit (&ch, 1) [0]; 2021 } 1606 QChar c = QString::fromLocal8Bit(&ch, 1)[0]; 2022 1607 } 2023 1608 #elif defined (Q_WS_MAC) 2024 1609 // TODO_NEW_CORE 2025 // if (aUniKey && aUniKey [0] && !aUniKey [1]) 2026 // processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL + 2027 // QChar (aUniKey [0]).toUpper().unicode()), 2028 // machineWindowWrapper()->menuBar()->actions()); 1610 // if (pUniKey && pUniKey [0] && !pUniKey [1]) 1611 // processed = processHotKey(QKeySequence (Qt::UNICODE_ACCEL + QChar(pUniKey[0]).toUpper().unicode()), 1612 // machineWindowWrapper()->menuBar()->actions()); 2029 1613 2030 1614 /* Don't consider the hot key as pressed since the guest never saw 2031 1615 * it. (probably a generic thing) */ 2032 m PressedKeys [aScan] &= ~whatPressed;2033 #endif 2034 2035 /* grab the key from Qt if processed, or pass it to Qt otherwise1616 m_pressedKeys[uScan] &= ~whatPressed; 1617 #endif 1618 1619 /* Grab the key from Qt if processed, or pass it to Qt otherwise 2036 1620 * in order to process non-alphanumeric keys in event(), after they are 2037 1621 * converted to Qt virtual keys. */ … … 2039 1623 } 2040 1624 2041 /* no more to do, if the host key is in action or the VM is paused*/1625 /* No more to do, if the host key is in action or the VM is paused: */ 2042 1626 if (m_bIsHostkeyPressed || isHostKey || machineWindowWrapper()->machineLogic()->isPaused()) 2043 1627 { 2044 /* grab the key from Qt and from VM if it's a host key,1628 /* Grab the key from Qt and from VM if it's a host key, 2045 1629 * otherwise just pass it to Qt */ 2046 1630 return isHostKey; … … 2048 1632 2049 1633 CKeyboard keyboard = m_console.GetKeyboard(); 2050 Assert 1634 Assert(!keyboard.isNull()); 2051 1635 2052 1636 #if defined (Q_WS_WIN32) 2053 1637 /* send pending WM_PAINT events */ 2054 ::UpdateWindow 1638 ::UpdateWindow(viewport()->winId()); 2055 1639 #endif 2056 1640 2057 1641 std::vector <LONG> scancodes(codes, &codes[count]); 2058 keyboard.PutScancodes 2059 2060 /* grab the key from Qt*/1642 keyboard.PutScancodes(QVector<LONG>::fromStdVector(scancodes)); 1643 1644 /* Grab the key from Qt: */ 2061 1645 return true; 2062 1646 } … … 2066 1650 int aWheelDelta, Qt::Orientation aWheelDir) 2067 1651 { 2068 #if 11652 #if 0 2069 1653 LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n", 2070 1654 __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(), … … 2123 1707 2124 1708 CMouse mouse = m_console.GetMouse(); 2125 mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(),2126 aGlobalPos.y() - mLastPos.y(),2127 1709 mouse.PutMouseEvent(aGlobalPos.x() - m_lastMousePos.x(), 1710 aGlobalPos.y() - m_lastMousePos.y(), 1711 wheelVertical, wheelHorizontal, state); 2128 1712 2129 1713 #if defined (Q_WS_MAC) … … 2156 1740 2157 1741 if (rect.contains (aGlobalPos, true)) 2158 m LastPos = aGlobalPos;1742 m_lastMousePos = aGlobalPos; 2159 1743 else 2160 1744 { 2161 mLastPos = rect.center(); 2162 QCursor::setPos (mLastPos); 2163 } 2164 1745 m_lastMousePos = rect.center(); 1746 QCursor::setPos (m_lastMousePos); 1747 } 2165 1748 #else /* !Q_WS_MAC */ 2166 1749 … … 2168 1751 * to simulate the endless moving */ 2169 1752 2170 # ifdef Q_WS_WIN321753 # ifdef Q_WS_WIN32 2171 1754 int we = viewport()->width() - 1; 2172 1755 int he = viewport()->height() - 1; … … 2183 1766 if (p != aPos) 2184 1767 { 2185 m LastPos = viewport()->mapToGlobal (p);2186 QCursor::setPos (m LastPos);1768 m_lastMousePos = viewport()->mapToGlobal (p); 1769 QCursor::setPos (m_lastMousePos); 2187 1770 } 2188 1771 else 2189 1772 { 2190 m LastPos = aGlobalPos;2191 } 2192 # else1773 m_lastMousePos = aGlobalPos; 1774 } 1775 # else 2193 1776 int we = QApplication::desktop()->width() - 1; 2194 1777 int he = QApplication::desktop()->height() - 1; … … 2205 1788 if (p != aGlobalPos) 2206 1789 { 2207 m LastPos = p;2208 QCursor::setPos (m LastPos);1790 m_lastMousePos = p; 1791 QCursor::setPos (m_lastMousePos); 2209 1792 } 2210 1793 else 2211 1794 { 2212 m LastPos = aGlobalPos;2213 } 2214 # endif1795 m_lastMousePos = aGlobalPos; 1796 } 1797 # endif 2215 1798 #endif /* !Q_WS_MAC */ 2216 1799 return true; /* stop further event handling */ … … 2218 1801 else /* !m_bIsMouseCaptured */ 2219 1802 { 2220 //if (machineWindowWrapper()->isTrueFullscreen()) // TODO check that! 2221 { 2222 if (mode != VBoxDefs::SDLMode) 2223 { 2224 /* try to automatically scroll the guest canvas if the 2225 * mouse is on the screen border */ 2226 /// @todo (r=dmik) better use a timer for autoscroll 2227 QRect scrGeo = QApplication::desktop()->screenGeometry (this); 2228 int dx = 0, dy = 0; 2229 if (scrGeo.width() < contentsWidth()) 2230 { 2231 if (scrGeo.left() == aGlobalPos.x()) dx = -1; 2232 if (scrGeo.right() == aGlobalPos.x()) dx = +1; 2233 } 2234 if (scrGeo.height() < contentsHeight()) 2235 { 2236 if (scrGeo.top() == aGlobalPos.y()) dy = -1; 2237 if (scrGeo.bottom() == aGlobalPos.y()) dy = +1; 2238 } 2239 if (dx || dy) 2240 scrollBy (dx, dy); 2241 } 2242 } 1803 #if 0 // TODO: Move that to fullscreen event-hjadler: 1804 if (mode() != VBoxDefs::SDLMode) 1805 { 1806 /* try to automatically scroll the guest canvas if the 1807 * mouse is on the screen border */ 1808 /// @todo (r=dmik) better use a timer for autoscroll 1809 QRect scrGeo = QApplication::desktop()->screenGeometry (this); 1810 int dx = 0, dy = 0; 1811 if (scrGeo.width() < contentsWidth()) 1812 { 1813 if (scrGeo.left() == aGlobalPos.x()) dx = -1; 1814 if (scrGeo.right() == aGlobalPos.x()) dx = +1; 1815 } 1816 if (scrGeo.height() < contentsHeight()) 1817 { 1818 if (scrGeo.top() == aGlobalPos.y()) dy = -1; 1819 if (scrGeo.bottom() == aGlobalPos.y()) dy = +1; 1820 } 1821 if (dx || dy) 1822 scrollBy(dx, dy); 1823 } 1824 #endif 2243 1825 2244 1826 if (m_bIsMouseAbsolute && m_bIsMouseIntegrated) … … 2247 1829 int vw = visibleWidth(), vh = visibleHeight(); 2248 1830 2249 if (mode != VBoxDefs::SDLMode)2250 { 2251 /* try to automatically scroll the guest canvas if the2252 * mouse goes outside its visible part */1831 if (mode() != VBoxDefs::SDLMode) 1832 { 1833 /* Try to automatically scroll the guest canvas if the 1834 * mouse goes outside its visible part: */ 2253 1835 2254 1836 int dx = 0; … … 2270 1852 mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical, 2271 1853 wheelHorizontal, state); 2272 return true; /* stop further event handling */1854 return true; 2273 1855 } 2274 1856 else 2275 1857 { 2276 if (hasFocus() && 2277 (aType == QEvent::MouseButtonRelease && 2278 aButtons == Qt::NoButton)) 1858 if (hasFocus() && (aType == QEvent::MouseButtonRelease && aButtons == Qt::NoButton)) 2279 1859 { 2280 1860 if (machineWindowWrapper()->machineLogic()->isPaused()) … … 2284 1864 else if (isRunning()) 2285 1865 { 2286 /* temporarily disable auto capture that will take 2287 * place after this dialog is dismissed because 2288 * the capture state is to be defined by the 2289 * dialog result itself */ 1866 /* Temporarily disable auto capture that will take place after this dialog is dismissed because 1867 * the capture state is to be defined by the dialog result itself: */ 2290 1868 m_bIsAutoCaptureDisabled = true; 2291 1869 bool autoConfirmed = false; … … 2293 1871 if (autoConfirmed) 2294 1872 m_bIsAutoCaptureDisabled = false; 2295 /* otherwise, the disable flag will be reset in 2296 * the next console view's foucs in event (since 2297 * may happen asynchronously on some platforms, 2298 * after we return from this code) */ 2299 1873 /* Otherwise, the disable flag will be reset in the next console view's foucs in event (since 1874 * may happen asynchronously on some platforms, after we return from this code): */ 2300 1875 if (ok) 2301 1876 { 2302 1877 #ifdef Q_WS_X11 2303 /* make sure that pending FocusOut events from the 2304 * previous message box are handled, otherwise the 2305 * mouse is immediately ungrabbed again */ 1878 /* Make sure that pending FocusOut events from the previous message box are handled, 1879 * otherwise the mouse is immediately ungrabbed again: */ 2306 1880 qApp->processEvents(); 2307 1881 #endif 2308 captureKbd 2309 captureMouse 1882 captureKbd(true); 1883 captureMouse(true); 2310 1884 } 2311 1885 } … … 2317 1891 } 2318 1892 2319 void UIMachineView::resizeEvent(QResizeEvent * )1893 void UIMachineView::resizeEvent(QResizeEvent *pEvent) 2320 1894 { 2321 1895 updateSliders(); 2322 1896 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 2323 QRect r = viewport()->geometry();2324 PostBoundsChanged(r );1897 QRect rectangle = viewport()->geometry(); 1898 PostBoundsChanged(rectangle); 2325 1899 #endif /* Q_WS_MAC */ 2326 } 2327 2328 void UIMachineView::moveEvent(QMoveEvent *) 1900 return QAbstractScrollArea::resizeEvent(pEvent); 1901 } 1902 1903 void UIMachineView::moveEvent(QMoveEvent *pEvent) 2329 1904 { 2330 1905 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) … … 2332 1907 PostBoundsChanged (r); 2333 1908 #endif /* Q_WS_MAC */ 2334 } 2335 2336 void UIMachineView::paintEvent(QPaintEvent *pe) 2337 { 2338 if (mPausedShot.isNull()) 2339 { 2340 /* delegate the paint function to the VBoxFrameBuffer interface */ 2341 if (mFrameBuf) 2342 mFrameBuf->paintEvent(pe); 1909 return QAbstractScrollArea::moveEvent(pEvent); 1910 } 1911 1912 void UIMachineView::paintEvent(QPaintEvent *pPaintEvent) 1913 { 1914 if (m_pauseShot.isNull()) 1915 { 1916 /* Delegate the paint function to the VBoxFrameBuffer interface: */ 1917 if (m_pFrameBuffer) 1918 m_pFrameBuffer->paintEvent(pPaintEvent); 2343 1919 #ifdef Q_WS_MAC 2344 1920 /* Update the dock icon if we are in the running state */ … … 2350 1926 2351 1927 #ifdef VBOX_GUI_USE_QUARTZ2D 2352 if (mode == VBoxDefs::Quartz2DMode && mFrameBuf)2353 { 2354 m FrameBuf->paintEvent(pe);1928 if (mode() == VBoxDefs::Quartz2DMode && m_pFrameBuffer) 1929 { 1930 m_pFrameBuffer->paintEvent(pPaintEvent); 2355 1931 updateDockIcon(); 2356 1932 } … … 2359 1935 { 2360 1936 /* We have a snapshot for the paused state: */ 2361 QRect r = p e->rect().intersect (viewport()->rect());1937 QRect r = pPaintEvent->rect().intersect (viewport()->rect()); 2362 1938 /* We have to disable paint on screen if we are using the regular painter */ 2363 1939 bool paintOnScreen = viewport()->testAttribute(Qt::WA_PaintOnScreen); 2364 1940 viewport()->setAttribute(Qt::WA_PaintOnScreen, false); 2365 1941 QPainter pnt(viewport()); 2366 pnt.drawPixmap(r.x(), r.y(), mPausedShot, 2367 r.x() + contentsX(), r.y() + contentsY(), 2368 r.width(), r.height()); 1942 pnt.drawPixmap(r.x(), r.y(), m_pauseShot, r.x() + contentsX(), r.y() + contentsY(), r.width(), r.height()); 2369 1943 /* Restore the attribute to its previous state */ 2370 1944 viewport()->setAttribute(Qt::WA_PaintOnScreen, paintOnScreen); … … 2375 1949 } 2376 1950 1951 #if defined(Q_WS_WIN32) 1952 1953 static HHOOK gKbdHook = NULL; 1954 static UIMachineView *gView = 0; 1955 LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 1956 { 1957 Assert(gView); 1958 if (gView && nCode == HC_ACTION && gView->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT *)lParam)) 1959 return 1; 1960 1961 return CallNextHookEx(NULL, nCode, wParam, lParam); 1962 } 1963 1964 bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event) 1965 { 1966 /* Sometimes it happens that Win inserts additional events on some key 1967 * press/release. For example, it prepends ALT_GR in German layout with 1968 * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary 1969 * to specially treat ALT_GR to enter additional chars to regular apps). 1970 * These events are definitely unwanted in VM, so filter them out. */ 1971 /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan 1972 * code 0x23a. If this is not passed through then it is impossible to 1973 * cancel CapsLock on a French keyboard. I didn't find any other examples 1974 * of these strange events. Let's hope we are not missing anything else 1975 * of importance! */ 1976 if (hasFocus() && (event.scanCode & ~0xFF)) 1977 { 1978 if (event.vkCode == VK_CAPITAL) 1979 return false; 1980 else 1981 return true; 1982 } 1983 1984 if (!m_bIsKeyboardCaptured) 1985 return false; 1986 1987 /* it's possible that a key has been pressed while the keyboard was not 1988 * captured, but is being released under the capture. Detect this situation 1989 * and return false to let Windows process the message normally and update 1990 * its key state table (to avoid the stuck key effect). */ 1991 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed; 1992 if ((event.flags & 0x80) /* released */ && 1993 ((event.vkCode == m_globalSettings.hostKey() && !m_bHostkeyInCapture) || 1994 (m_pressedKeys[event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed)) 1995 return false; 1996 1997 MSG message; 1998 message.hwnd = winId(); 1999 message.message = msg; 2000 message.wParam = event.vkCode; 2001 message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24; 2002 2003 /* Windows sets here the extended bit when the Right Shift key is pressed, 2004 * which is totally wrong. Undo it. */ 2005 if (event.vkCode == VK_RSHIFT) 2006 message.lParam &= ~0x1000000; 2007 2008 /* we suppose here that this hook is always called on the main GUI thread */ 2009 long dummyResult; 2010 return winEvent(&message, &dummyResult); 2011 } 2012 2013 bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */) 2014 { 2015 if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN || 2016 aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP)) 2017 return false; 2018 2019 /* Check for the special flag possibly set at the end of this function */ 2020 if (aMsg->lParam & (0x1 << 25)) 2021 { 2022 aMsg->lParam &= ~(0x1 << 25); 2023 return false; 2024 } 2025 2026 int scan = (aMsg->lParam >> 16) & 0x7F; 2027 /* scancodes 0x80 and 0x00 are ignored */ 2028 if (!scan) 2029 return true; 2030 2031 int vkey = aMsg->wParam; 2032 2033 /* When one of the SHIFT keys is held and one of the cursor movement 2034 * keys is pressed, Windows duplicates SHIFT press/release messages, 2035 * but with the virtual key code set to 0xFF. These virtual keys are also 2036 * sent in some other situations (Pause, PrtScn, etc.). Ignore such 2037 * messages. */ 2038 if (vkey == 0xFF) 2039 return true; 2040 2041 int flags = 0; 2042 if (aMsg->lParam & 0x1000000) 2043 flags |= KeyExtended; 2044 if (!(aMsg->lParam & 0x80000000)) 2045 flags |= KeyPressed; 2046 2047 switch (vkey) 2048 { 2049 case VK_SHIFT: 2050 case VK_CONTROL: 2051 case VK_MENU: 2052 { 2053 /* overcome stupid Win32 modifier key generalization */ 2054 int keyscan = scan; 2055 if (flags & KeyExtended) 2056 keyscan |= 0xE000; 2057 switch (keyscan) 2058 { 2059 case 0x002A: vkey = VK_LSHIFT; break; 2060 case 0x0036: vkey = VK_RSHIFT; break; 2061 case 0x001D: vkey = VK_LCONTROL; break; 2062 case 0xE01D: vkey = VK_RCONTROL; break; 2063 case 0x0038: vkey = VK_LMENU; break; 2064 case 0xE038: vkey = VK_RMENU; break; 2065 } 2066 break; 2067 } 2068 case VK_NUMLOCK: 2069 /* Win32 sets the extended bit for the NumLock key. Reset it. */ 2070 flags &= ~KeyExtended; 2071 break; 2072 case VK_SNAPSHOT: 2073 flags |= KeyPrint; 2074 break; 2075 case VK_PAUSE: 2076 flags |= KeyPause; 2077 break; 2078 } 2079 2080 bool result = keyEvent(vkey, scan, flags); 2081 if (!result && m_bIsKeyboardCaptured) 2082 { 2083 /* keyEvent() returned that it didn't process the message, but since the 2084 * keyboard is captured, we don't want to pass it to Windows. We just want 2085 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 2086 * shortcuts for example). So send it direcltly to the window with the 2087 * special flag in the reserved area of lParam (to avoid recursion). */ 2088 ::SendMessage(aMsg->hwnd, aMsg->message, 2089 aMsg->wParam, aMsg->lParam | (0x1 << 25)); 2090 return true; 2091 } 2092 2093 /* These special keys have to be handled by Windows as well to update the 2094 * internal modifier state and to enable/disable the keyboard LED */ 2095 if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT) 2096 return false; 2097 2098 return result; 2099 } 2100 2101 #elif defined(Q_WS_PM) 2102 2103 bool UIMachineView::pmEvent(QMSG *aMsg) 2104 { 2105 if (aMsg->msg == UM_PREACCEL_CHAR) 2106 { 2107 /* We are inside the input hook 2108 * let the message go through the normal system pipeline. */ 2109 if (!m_bIsKeyboardCaptured) 2110 return false; 2111 } 2112 2113 if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR) 2114 return false; 2115 2116 /* check for the special flag possibly set at the end of this function */ 2117 if (SHORT2FROMMP(aMsg->mp2) & 0x8000) 2118 { 2119 aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000); 2120 return false; 2121 } 2122 2123 USHORT ch = SHORT1FROMMP(aMsg->mp2); 2124 USHORT f = SHORT1FROMMP(aMsg->mp1); 2125 2126 int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1); 2127 if (!scan || scan > 0x7F) 2128 return true; 2129 2130 int vkey = QIHotKeyEdit::virtualKey(aMsg); 2131 2132 int flags = 0; 2133 2134 if ((ch & 0xFF) == 0xE0) 2135 { 2136 flags |= KeyExtended; 2137 scan = ch >> 8; 2138 } 2139 else if (scan == 0x5C && (ch & 0xFF) == '/') 2140 { 2141 /* this is the '/' key on the keypad */ 2142 scan = 0x35; 2143 flags |= KeyExtended; 2144 } 2145 else 2146 { 2147 /* For some keys, the scan code passed in QMSG is a pseudo scan 2148 * code. We replace it with a real hardware scan code, according to 2149 * http://www.computer-engineering.org/ps2keyboard/scancodes1.html. 2150 * Also detect Pause and PrtScn and set flags. */ 2151 switch (vkey) 2152 { 2153 case VK_ENTER: scan = 0x1C; flags |= KeyExtended; break; 2154 case VK_CTRL: scan = 0x1D; flags |= KeyExtended; break; 2155 case VK_ALTGRAF: scan = 0x38; flags |= KeyExtended; break; 2156 case VK_LWIN: scan = 0x5B; flags |= KeyExtended; break; 2157 case VK_RWIN: scan = 0x5C; flags |= KeyExtended; break; 2158 case VK_WINMENU: scan = 0x5D; flags |= KeyExtended; break; 2159 case VK_FORWARD: scan = 0x69; flags |= KeyExtended; break; 2160 case VK_BACKWARD: scan = 0x6A; flags |= KeyExtended; break; 2161 #if 0 2162 /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully 2163 // clear what is more correct 2164 case VK_BREAK: scan = 0x46; flags |= KeyExtended; break; 2165 #else 2166 case VK_BREAK: scan = 0; flags |= KeyPause; break; 2167 #endif 2168 case VK_PAUSE: scan = 0; flags |= KeyPause; break; 2169 case VK_PRINTSCRN: scan = 0; flags |= KeyPrint; break; 2170 default:; 2171 } 2172 } 2173 2174 if (!(f & KC_KEYUP)) 2175 flags |= KeyPressed; 2176 2177 bool result = keyEvent (vkey, scan, flags); 2178 if (!result && m_bIsKeyboardCaptured) 2179 { 2180 /* keyEvent() returned that it didn't process the message, but since the 2181 * keyboard is captured, we don't want to pass it to PM. We just want 2182 * to let Qt process the message (to handle non-alphanumeric <HOST>+key 2183 * shortcuts for example). So send it direcltly to the window with the 2184 * special flag in the reserved area of lParam (to avoid recursion). */ 2185 ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1, 2186 MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000)); 2187 return true; 2188 } 2189 return result; 2190 } 2191 2192 #elif defined(Q_WS_X11) 2193 2194 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg) 2195 { 2196 XEvent *pKeyEvent = (XEvent*)pvArg; 2197 if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode)) 2198 return True; 2199 else 2200 return False; 2201 } 2202 2203 bool UIMachineView::x11Event(XEvent *pEvent) 2204 { 2205 switch (pEvent->type) 2206 { 2207 /* We have to handle XFocusOut right here as this event is not passed 2208 * to UIMachineView::event(). Handling this event is important for 2209 * releasing the keyboard before the screen saver gets active. */ 2210 case XFocusOut: 2211 case XFocusIn: 2212 if (isRunning()) 2213 focusEvent(pEvent->type == XFocusIn); 2214 return false; 2215 case XKeyPress: 2216 case XKeyRelease: 2217 break; 2218 default: 2219 return false; /* pass the event to Qt */ 2220 } 2221 2222 /* Translate the keycode to a PC scan code. */ 2223 unsigned scan = handleXKeyEvent(pEvent); 2224 2225 /* scancodes 0x00 (no valid translation) and 0x80 are ignored */ 2226 if (!scan & 0x7F) 2227 return true; 2228 2229 /* Fix for http://www.virtualbox.org/ticket/1296: 2230 * when X11 sends events for repeated keys, it always inserts an 2231 * XKeyRelease before the XKeyPress. */ 2232 XEvent returnEvent; 2233 if ((pEvent->type == XKeyRelease) && (XCheckIfEvent(pEvent->xkey.display, &returnEvent, 2234 VBoxConsoleViewCompEvent, (XPointer)pEvent) == True)) 2235 { 2236 XPutBackEvent(pEvent->xkey.display, &returnEvent); 2237 /* Discard it, don't pass it to Qt. */ 2238 return true; 2239 } 2240 2241 KeySym ks = ::XKeycodeToKeysym(pEvent->xkey.display, pEvent->xkey.keycode, 0); 2242 2243 int flags = 0; 2244 if (scan >> 8) 2245 flags |= KeyExtended; 2246 if (pEvent->type == XKeyPress) 2247 flags |= KeyPressed; 2248 2249 /* Remove the extended flag */ 2250 scan &= 0x7F; 2251 2252 switch (ks) 2253 { 2254 case XK_Print: 2255 flags |= KeyPrint; 2256 break; 2257 case XK_Pause: 2258 flags |= KeyPause; 2259 break; 2260 } 2261 2262 return keyEvent(ks, scan, flags); 2263 } 2264 2265 #elif defined(Q_WS_MAC) 2266 2267 bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent) 2268 { 2269 bool ret = false; 2270 UInt32 EventKind = ::GetEventKind(inEvent); 2271 if (EventKind != kEventRawKeyModifiersChanged) 2272 { 2273 /* convert keycode to set 1 scan code. */ 2274 UInt32 keyCode = ~0U; 2275 ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode); 2276 unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode); 2277 if (scanCode) 2278 { 2279 /* calc flags. */ 2280 int flags = 0; 2281 if (EventKind != kEventRawKeyUp) 2282 flags |= KeyPressed; 2283 if (scanCode & VBOXKEY_EXTENDED) 2284 flags |= KeyExtended; 2285 /** @todo KeyPause, KeyPrint. */ 2286 scanCode &= VBOXKEY_SCANCODE_MASK; 2287 2288 /* get the unicode string (if present). */ 2289 AssertCompileSize(wchar_t, 2); 2290 AssertCompileSize(UniChar, 2); 2291 ByteCount cbWritten = 0; 2292 wchar_t ucs[8]; 2293 if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 2294 sizeof(ucs), &cbWritten, &ucs[0]) != 0) 2295 cbWritten = 0; 2296 ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */ 2297 2298 ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL); 2299 } 2300 } 2301 else 2302 { 2303 /* May contain multiple modifier changes, kind of annoying. */ 2304 UInt32 newMask = 0; 2305 ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, 2306 sizeof(newMask), NULL, &newMask); 2307 newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent); 2308 UInt32 changed = newMask ^ m_darwinKeyModifiers; 2309 if (changed) 2310 { 2311 for (UInt32 bit = 0; bit < 32; bit++) 2312 { 2313 if (!(changed & (1 << bit))) 2314 continue; 2315 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit); 2316 if (!scanCode) 2317 continue; 2318 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit); 2319 Assert(keyCode); 2320 2321 if (!(scanCode & VBOXKEY_LOCK)) 2322 { 2323 unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0; 2324 if (scanCode & VBOXKEY_EXTENDED) 2325 flags |= KeyExtended; 2326 scanCode &= VBOXKEY_SCANCODE_MASK; 2327 ret |= keyEvent(keyCode, scanCode & 0xff, flags); 2328 } 2329 else 2330 { 2331 unsigned flags = 0; 2332 if (scanCode & VBOXKEY_EXTENDED) 2333 flags |= KeyExtended; 2334 scanCode &= VBOXKEY_SCANCODE_MASK; 2335 keyEvent(keyCode, scanCode, flags | KeyPressed); 2336 keyEvent(keyCode, scanCode, flags); 2337 } 2338 } 2339 } 2340 2341 m_darwinKeyModifiers = newMask; 2342 2343 /* Always return true here because we'll otherwise getting a Qt event 2344 we don't want and that will only cause the Pause warning to pop up. */ 2345 ret = true; 2346 } 2347 2348 return ret; 2349 } 2350 2351 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab) 2352 { 2353 m_fKeyboardGrabbed = fGrab; 2354 if (fGrab) 2355 { 2356 /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */ 2357 ::CGSetLocalEventsSuppressionInterval(0.0); 2358 setMouseCoalescingEnabled(false); 2359 2360 /* Register the event callback/hook and grab the keyboard. */ 2361 # ifdef QT_MAC_USE_COCOA 2362 ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */ 2363 UIMachineView::darwinEventHandlerProc, this); 2364 2365 # else /* QT_MAC_USE_COCOA */ 2366 EventTypeSpec eventTypes[6]; 2367 eventTypes[0].eventClass = kEventClassKeyboard; 2368 eventTypes[0].eventKind = kEventRawKeyDown; 2369 eventTypes[1].eventClass = kEventClassKeyboard; 2370 eventTypes[1].eventKind = kEventRawKeyUp; 2371 eventTypes[2].eventClass = kEventClassKeyboard; 2372 eventTypes[2].eventKind = kEventRawKeyRepeat; 2373 eventTypes[3].eventClass = kEventClassKeyboard; 2374 eventTypes[3].eventKind = kEventRawKeyModifiersChanged; 2375 /* For ignorning Command-H and Command-Q which aren't affected by the 2376 * global hotkey stuff (doesn't work well): */ 2377 eventTypes[4].eventClass = kEventClassCommand; 2378 eventTypes[4].eventKind = kEventCommandProcess; 2379 eventTypes[5].eventClass = kEventClassCommand; 2380 eventTypes[5].eventKind = kEventCommandUpdateStatus; 2381 2382 EventHandlerUPP eventHandler = ::NewEventHandlerUPP(UIMachineView::darwinEventHandlerProc); 2383 2384 m_darwinEventHandlerRef = NULL; 2385 ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0], 2386 this, &m_darwinEventHandlerRef); 2387 ::DisposeEventHandlerUPP(eventHandler); 2388 # endif /* !QT_MAC_USE_COCOA */ 2389 2390 ::DarwinGrabKeyboard (false); 2391 } 2392 else 2393 { 2394 ::DarwinReleaseKeyboard(); 2395 # ifdef QT_MAC_USE_COCOA 2396 ::VBoxCocoaApplication_unsetCallback(UINT32_MAX, /** @todo fix mask */ 2397 UIMachineView::darwinEventHandlerProc, this); 2398 # else /* QT_MAC_USE_COCOA */ 2399 if (m_darwinEventHandlerRef) 2400 { 2401 ::RemoveEventHandler(m_darwinEventHandlerRef); 2402 m_darwinEventHandlerRef = NULL; 2403 } 2404 # endif /* !QT_MAC_USE_COCOA */ 2405 } 2406 } 2407 2408 # ifdef QT_MAC_USE_COCOA 2409 bool UIMachineView::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser) 2410 { 2411 UIMachineView *view = (UIMachineView*)pvUser; 2412 EventRef inEvent = (EventRef)pvCarbonEvent; 2413 UInt32 eventClass = ::GetEventClass(inEvent); 2414 2415 /* Check if this is an application key combo. In that case we will not pass 2416 * the event to the guest, but let the host process it. */ 2417 if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent)) 2418 return false; 2419 2420 /* All keyboard class events needs to be handled. */ 2421 if (eventClass == kEventClassKeyboard) 2422 { 2423 if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent)) 2424 return true; 2425 } 2426 /* Pass the event along. */ 2427 return false; 2428 } 2429 # else /* QT_MAC_USE_COCOA */ 2430 2431 pascal OSStatus UIMachineView::darwinEventHandlerProc(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 2432 { 2433 UIMachineView *view = static_cast<UIMachineView *> (inUserData); 2434 UInt32 eventClass = ::GetEventClass (inEvent); 2435 2436 /* Not sure but this seems an triggered event if the spotlight searchbar is 2437 * displayed. So flag that the host key isn't pressed alone. */ 2438 if (eventClass == 'cgs ' && view->m_bIsHostkeyPressed && ::GetEventKind (inEvent) == 0x15) 2439 view->m_bIsHostkeyAlone = false; 2440 2441 if (eventClass == kEventClassKeyboard) 2442 { 2443 if (view->darwinKeyboardEvent (NULL, inEvent)) 2444 return 0; 2445 } 2446 2447 /* 2448 * Command-H and Command-Q aren't properly disabled yet, and it's still 2449 * possible to use the left command key to invoke them when the keyboard 2450 * is captured. We discard the events these if the keyboard is captured 2451 * as a half measure to prevent unexpected behaviour. However, we don't 2452 * get any key down/up events, so these combinations are dead to the guest... 2453 */ 2454 else if (eventClass == kEventClassCommand) 2455 { 2456 if (view->m_bIsKeyboardCaptured) 2457 return 0; 2458 } 2459 return ::CallNextEventHandler(inHandlerCallRef, inEvent); 2460 } 2461 # endif /* !QT_MAC_USE_COCOA */ 2462 2463 #endif 2464 2377 2465 void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount) 2378 2466 { … … 2380 2468 * This function will add up to 6 additional keycodes to codes. */ 2381 2469 2382 #if defined 2470 #if defined(Q_WS_X11) 2383 2471 2384 2472 Window wDummy1, wDummy2; … … 2403 2491 XFreeModifiermap(map); 2404 2492 2405 if (m uNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum)))2406 { 2407 -- m uNumLockAdaptionCnt;2493 if (m_uNumLockAdaptionCnt && (m_numLock ^ !!(uMask & uKeyMaskNum))) 2494 { 2495 -- m_uNumLockAdaptionCnt; 2408 2496 piCodes[(*puCount)++] = 0x45; 2409 2497 piCodes[(*puCount)++] = 0x45 | 0x80; 2410 2498 } 2411 if (m uCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps)))2412 { 2413 m uCapsLockAdaptionCnt--;2499 if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(uMask & uKeyMaskCaps))) 2500 { 2501 m_uCapsLockAdaptionCnt--; 2414 2502 piCodes[(*puCount)++] = 0x3a; 2415 2503 piCodes[(*puCount)++] = 0x3a | 0x80; … … 2417 2505 * capslock. For simplicity, only do this if shift is not 2418 2506 * already held down. */ 2419 if (m CapsLock && !(mPressedKeys[0x2a] & IsKeyPressed))2507 if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed)) 2420 2508 { 2421 2509 piCodes[(*puCount)++] = 0x2a; … … 2424 2512 } 2425 2513 2426 #elif defined 2427 2428 if (m uNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK))))2429 { 2430 m uNumLockAdaptionCnt--;2514 #elif defined(Q_WS_WIN32) 2515 2516 if (m_uNumLockAdaptionCnt && (m_numLock ^ !!(GetKeyState(VK_NUMLOCK)))) 2517 { 2518 m_uNumLockAdaptionCnt--; 2431 2519 piCodes[(*puCount)++] = 0x45; 2432 2520 piCodes[(*puCount)++] = 0x45 | 0x80; 2433 2521 } 2434 if (m uCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL))))2435 { 2436 m uCapsLockAdaptionCnt--;2522 if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(GetKeyState(VK_CAPITAL)))) 2523 { 2524 m_uCapsLockAdaptionCnt--; 2437 2525 piCodes[(*puCount)++] = 0x3a; 2438 2526 piCodes[(*puCount)++] = 0x3a | 0x80; … … 2440 2528 * capslock. For simplicity, only do this if shift is not 2441 2529 * already held down. */ 2442 if (m CapsLock && !(mPressedKeys[0x2a] & IsKeyPressed))2530 if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed)) 2443 2531 { 2444 2532 piCodes[(*puCount)++] = 0x2a; … … 2447 2535 } 2448 2536 2449 #elif defined 2450 2451 /* if (m uNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */2452 if (m uCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))2453 { 2454 m uCapsLockAdaptionCnt--;2537 #elif defined(Q_WS_MAC) 2538 2539 /* if (m_uNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */ 2540 if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock))) 2541 { 2542 m_uCapsLockAdaptionCnt--; 2455 2543 piCodes[(*puCount)++] = 0x3a; 2456 2544 piCodes[(*puCount)++] = 0x3a | 0x80; … … 2458 2546 * capslock. For simplicity, only do this if shift is not 2459 2547 * already held down. */ 2460 if (m CapsLock && !(mPressedKeys[0x2a] & IsKeyPressed))2548 if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed)) 2461 2549 { 2462 2550 piCodes[(*puCount)++] = 0x2a; … … 2472 2560 } 2473 2561 2474 void UIMachineView::scrollBy(int dx, int dy)2475 {2476 horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);2477 verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);2478 }2479 2480 2562 QPoint UIMachineView::viewportToContents(const QPoint &vp) const 2481 2563 { … … 2488 2570 QSize m = maximumViewportSize(); 2489 2571 2490 QSize v = QSize(m FrameBuf->width(), mFrameBuf->height());2572 QSize v = QSize(m_pFrameBuffer->width(), m_pFrameBuffer->height()); 2491 2573 /* no scroll bars needed */ 2492 2574 if (m.expandedTo(v) == m) … … 2499 2581 } 2500 2582 2583 void UIMachineView::scrollBy(int dx, int dy) 2584 { 2585 horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx); 2586 verticalScrollBar()->setValue(verticalScrollBar()->value() + dy); 2587 } 2588 2501 2589 #ifdef VBOX_WITH_VIDEOHWACCEL 2502 void UIMachineView::scrollContentsBy (int dx, int dy) 2503 { 2504 if (mFrameBuf) 2505 { 2506 mFrameBuf->viewportScrolled(dx, dy); 2507 } 2508 QAbstractScrollArea::scrollContentsBy (dx, dy); 2509 } 2510 #endif 2511 2512 void UIMachineView::onStateChange(KMachineState state) 2513 { 2514 switch (state) 2515 { 2516 case KMachineState_Paused: 2517 case KMachineState_TeleportingPausedVM: 2518 { 2519 if ( mode != VBoxDefs::TimerMode 2520 && mFrameBuf 2521 && ( state != KMachineState_TeleportingPausedVM 2522 || mLastState != KMachineState_Teleporting) 2523 ) 2524 { 2525 /* 2526 * Take a screen snapshot. Note that TakeScreenShot() always 2527 * needs a 32bpp image 2528 */ 2529 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32); 2530 CDisplay dsp = m_console.GetDisplay(); 2531 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height()); 2532 /* 2533 * TakeScreenShot() may fail if, e.g. the Paused notification 2534 * was delivered after the machine execution was resumed. It's 2535 * not fatal. 2536 */ 2537 if (dsp.isOk()) 2538 { 2539 dimImage (shot); 2540 mPausedShot = QPixmap::fromImage (shot); 2541 /* fully repaint to pick up mPausedShot */ 2542 repaint(); 2543 } 2544 } 2545 /* fall through */ 2546 } 2547 case KMachineState_Stuck: 2548 { 2549 /* reuse the focus event handler to uncapture everything */ 2550 if (hasFocus()) 2551 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */); 2552 break; 2553 } 2554 case KMachineState_Running: 2555 { 2556 if ( mLastState == KMachineState_Paused 2557 || mLastState == KMachineState_TeleportingPausedVM 2558 ) 2559 { 2560 if (mode != VBoxDefs::TimerMode && mFrameBuf) 2561 { 2562 /* reset the pixmap to free memory */ 2563 mPausedShot = QPixmap (); 2564 /* 2565 * ask for full guest display update (it will also update 2566 * the viewport through IFramebuffer::NotifyUpdate) 2567 */ 2568 CDisplay dsp = m_console.GetDisplay(); 2569 dsp.InvalidateAndUpdate(); 2570 } 2571 } 2572 /* reuse the focus event handler to capture input */ 2573 if (hasFocus()) 2574 focusEvent (true /* aHasFocus */); 2575 break; 2576 } 2577 default: 2578 break; 2579 } 2580 2581 mLastState = state; 2582 } 2583 2584 void UIMachineView::captureKbd(bool aCapture, bool aEmitSignal /* = true */) 2585 { 2586 //AssertMsg(m_bIsAttached, ("Console must be attached")); 2587 2588 if (m_bIsKeyboardCaptured == aCapture) 2590 void UIMachineView::scrollContentsBy(int dx, int dy) 2591 { 2592 if (m_pFrameBuffer) 2593 { 2594 m_pFrameBuffer->viewportScrolled(dx, dy); 2595 } 2596 QAbstractScrollArea::scrollContentsBy(dx, dy); 2597 } 2598 #endif 2599 2600 void UIMachineView::emitKeyboardStateChanged() 2601 { 2602 emit keyboardStateChanged((m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) | 2603 (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0)); 2604 } 2605 2606 void UIMachineView::emitMouseStateChanged() 2607 { 2608 emit mouseStateChanged((m_bIsMouseCaptured ? UIMouseStateType_MouseCaptured : 0) | 2609 (m_bIsMouseAbsolute ? UIMouseStateType_MouseAbsolute : 0) | 2610 (!m_bIsMouseIntegrated ? UIMouseStateType_MouseAbsoluteDisabled : 0)); 2611 } 2612 2613 void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */) 2614 { 2615 if (m_bIsKeyboardCaptured == fCapture) 2589 2616 return; 2590 2617 2591 /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is 2592 * used instead. On X11, we use XGrabKey instead of XGrabKeyboard (called 2593 * by QWidget::grabKeyboard()) because the latter causes problems under 2594 * metacity 2.16 (in particular, due to a bug, a window cannot be moved 2595 * using the mouse if it is currently grabing the keyboard). On Mac OS X, 2596 * we use the Qt methods + disabling global hot keys + watching modifiers 2618 /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. 2619 * On X11, we use XGrabKey instead of XGrabKeyboard (called by QWidget::grabKeyboard()) 2620 * because the latter causes problems under metacity 2.16 (in particular, due to a bug, 2621 * a window cannot be moved using the mouse if it is currently grabing the keyboard). 2622 * On Mac OS X, we use the Qt methods + disabling global hot keys + watching modifiers 2597 2623 * (for right/left separation). */ 2598 #if defined 2624 #if defined(Q_WS_WIN32) 2599 2625 /**/ 2600 #elif defined 2601 if ( aCapture)2626 #elif defined(Q_WS_X11) 2627 if (fCapture) 2602 2628 XGrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId(), False, GrabModeAsync, GrabModeAsync); 2603 2629 else 2604 XUngrabKey(QX11Info::display(), 2605 #elif defined 2606 if ( aCapture)2630 XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId()); 2631 #elif defined(Q_WS_MAC) 2632 if (fCapture) 2607 2633 { 2608 2634 ::DarwinDisableGlobalHotKeys(true); … … 2615 2641 } 2616 2642 #else 2617 if ( aCapture)2643 if (fCapture) 2618 2644 grabKeyboard(); 2619 2645 else … … 2621 2647 #endif 2622 2648 2623 m_bIsKeyboardCaptured = aCapture;2624 2625 if ( aEmitSignal)2649 m_bIsKeyboardCaptured = fCapture; 2650 2651 if (fEmitSignal) 2626 2652 emitKeyboardStateChanged(); 2627 2653 } 2628 2654 2629 void UIMachineView::captureMouse(bool aCapture, bool aEmitSignal /* = true */) 2630 { 2631 //AssertMsg (m_bIsAttached, ("Console must be attached")); 2632 2633 if (m_bIsMouseCaptured == aCapture) 2655 void UIMachineView::captureMouse(bool fCapture, bool fEmitSignal /* = true */) 2656 { 2657 if (m_bIsMouseCaptured == fCapture) 2634 2658 return; 2635 2659 2636 if ( aCapture)2637 { 2638 /* memorize the host position where the cursor was captured*/2639 m CapturedPos = QCursor::pos();2660 if (fCapture) 2661 { 2662 /* Memorize the host position where the cursor was captured: */ 2663 m_capturedMousePos = QCursor::pos(); 2640 2664 #ifdef Q_WS_WIN32 2641 2665 viewport()->setCursor (QCursor (Qt::BlankCursor)); 2642 /* move the mouse to the center of the visible area*/2666 /* Move the mouse to the center of the visible area: */ 2643 2667 QCursor::setPos (mapToGlobal (visibleRegion().boundingRect().center())); 2644 m LastPos = QCursor::pos();2668 m_lastMousePos = QCursor::pos(); 2645 2669 #elif defined (Q_WS_MAC) 2646 /* move the mouse to the center of the visible area*/2647 m LastPos = mapToGlobal (visibleRegion().boundingRect().center());2648 QCursor::setPos (m LastPos);2649 /* grab all mouse events.*/2670 /* Move the mouse to the center of the visible area: */ 2671 m_lastMousePos = mapToGlobal (visibleRegion().boundingRect().center()); 2672 QCursor::setPos (m_lastMousePos); 2673 /* Grab all mouse events: */ 2650 2674 viewport()->grabMouse(); 2651 2675 #else 2652 2676 viewport()->grabMouse(); 2653 m LastPos = QCursor::pos();2677 m_lastMousePos = QCursor::pos(); 2654 2678 #endif 2655 2679 } … … 2659 2683 viewport()->releaseMouse(); 2660 2684 #endif 2661 /* release mouse buttons*/2685 /* Release mouse buttons: */ 2662 2686 CMouse mouse = m_console.GetMouse(); 2663 2687 mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0); 2664 2688 } 2665 2689 2666 m_bIsMouseCaptured = aCapture;2690 m_bIsMouseCaptured = fCapture; 2667 2691 2668 2692 updateMouseClipping(); 2669 2693 2670 if ( aEmitSignal)2694 if (fEmitSignal) 2671 2695 emitMouseStateChanged(); 2672 2696 } 2673 2697 2674 bool UIMachineView::processHotKey(const QKeySequence &aKey, const QList <QAction*> &aData) 2675 { 2676 foreach (QAction *pAction, aData) 2698 void UIMachineView::saveKeyStates() 2699 { 2700 ::memcpy(m_pressedKeysCopy, m_pressedKeys, sizeof(m_pressedKeys)); 2701 } 2702 2703 bool UIMachineView::processHotKey(const QKeySequence &key, const QList<QAction*> &actions) 2704 { 2705 // TODO: Make it work for all modes: 2706 foreach (QAction *pAction, actions) 2677 2707 { 2678 2708 if (QMenu *menu = pAction->menu()) 2679 2709 { 2680 2710 /* Process recursively for each sub-menu */ 2681 if (processHotKey( aKey, menu->actions()))2711 if (processHotKey(key, menu->actions())) 2682 2712 return true; 2683 2713 } … … 2687 2717 if (pAction->isEnabled() && !hotkey.isEmpty()) 2688 2718 { 2689 if ( aKey.matches(QKeySequence (hotkey)) == QKeySequence::ExactMatch)2719 if (key.matches(QKeySequence (hotkey)) == QKeySequence::ExactMatch) 2690 2720 { 2691 2721 /* We asynchronously post a special event instead of calling … … 2708 2738 void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */) 2709 2739 { 2710 //AssertMsg(m_bIsAttached, ("Console must be attached"));2711 2712 2740 CKeyboard keyboard = m_console.GetKeyboard(); 2713 2741 bool fSentRESEND = false; 2714 2742 2715 /* send a dummy scan code (RESEND) to prevent the guest OS from recognizing2743 /* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing 2716 2744 * a single key click (for ex., Alt) and performing an unwanted action 2717 2745 * (for ex., activating the menu) when we release all pressed keys below. 2718 2746 * Note, that it's just a guess that sending RESEND will give the desired 2719 2747 * effect :), but at least it works with NT and W2k guests. */ 2720 2721 for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++) 2722 { 2723 if (mPressedKeys[i] & IsKeyPressed) 2748 for (uint i = 0; i < SIZEOF_ARRAY (m_pressedKeys); i++) 2749 { 2750 if (m_pressedKeys[i] & IsKeyPressed) 2724 2751 { 2725 2752 if (!fSentRESEND) … … 2730 2757 keyboard.PutScancode(i | 0x80); 2731 2758 } 2732 else if (m PressedKeys[i] & IsExtKeyPressed)2759 else if (m_pressedKeys[i] & IsExtKeyPressed) 2733 2760 { 2734 2761 if (!fSentRESEND) … … 2742 2769 keyboard.PutScancodes(codes); 2743 2770 } 2744 m PressedKeys[i] = 0;2771 m_pressedKeys[i] = 0; 2745 2772 } 2746 2773 … … 2749 2776 2750 2777 #ifdef Q_WS_MAC 2751 /* clear most of the modifiers.*/2752 m DarwinKeyModifiers &=2778 /* Clear most of the modifiers: */ 2779 m_darwinKeyModifiers &= 2753 2780 alphaLock | kEventKeyModifierNumLockMask | 2754 2781 (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey())); … … 2758 2785 } 2759 2786 2760 void UIMachineView::saveKeyStates()2761 {2762 ::memcpy(mPressedKeysCopy, mPressedKeys, sizeof(mPressedKeys));2763 }2764 2765 2787 void UIMachineView::sendChangedKeyStates() 2766 2788 { 2767 //AssertMsg(m_bIsAttached, ("Console must be attached"));2768 2769 2789 QVector <LONG> codes(2); 2770 2790 CKeyboard keyboard = m_console.GetKeyboard(); 2771 for (uint i = 0; i < SIZEOF_ARRAY(m PressedKeys); ++ i)2772 { 2773 uint8_t os = m PressedKeysCopy[i];2774 uint8_t ns = m PressedKeys[i];2791 for (uint i = 0; i < SIZEOF_ARRAY(m_pressedKeys); ++ i) 2792 { 2793 uint8_t os = m_pressedKeysCopy[i]; 2794 uint8_t ns = m_pressedKeys[i]; 2775 2795 if ((os & IsKeyPressed) != (ns & IsKeyPressed)) 2776 2796 { … … 2793 2813 void UIMachineView::updateMouseClipping() 2794 2814 { 2795 //AssertMsg(m_bIsAttached, ("Console must be attached"));2796 2797 2815 if (m_bIsMouseCaptured) 2798 2816 { … … 2811 2829 #endif 2812 2830 /* return the cursor to where it was when we captured it and show it */ 2813 QCursor::setPos(m CapturedPos);2831 QCursor::setPos(m_capturedMousePos); 2814 2832 viewport()->unsetCursor(); 2815 2833 } 2816 2834 } 2817 2835 2818 #if 0 2819 void UIMachineView::setPointerShape(MousePointerChangeEvent *pEvent)2820 { 2821 if (pEvent->shapeData() != NULL)2822 { 2823 2824 2825 const uchar *srcAndMaskPtr = pEvent->shapeData();2826 uint andMaskSize = (pEvent->width() + 7) / 8 * pEvent->height();2827 const uchar *srcShapePtr = pEvent->shapeData()+ ((andMaskSize + 3) & ~3);2828 uint srcShapePtrScan = pEvent->width()* 4;2836 void UIMachineView::setPointerShape(const uchar *pShapeData, bool fHasAlpha, 2837 uint uXHot, uint uYHot, uint uWidth, uint uHeight) 2838 { 2839 AssertMsg(pShapeData, ("Shape data must not be NULL!\n")); 2840 2841 bool ok = false; 2842 2843 const uchar *srcAndMaskPtr = pShapeData; 2844 uint andMaskSize = (uWidth + 7) / 8 * uHeight; 2845 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3); 2846 uint srcShapePtrScan = uWidth * 4; 2829 2847 2830 2848 #if defined (Q_WS_WIN) 2831 2849 2832 BITMAPV5HEADER bi; 2833 HBITMAP hBitmap; 2834 void *lpBits; 2835 2836 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER)); 2837 bi.bV5Size = sizeof(BITMAPV5HEADER); 2838 bi.bV5Width = pEvent->width(); 2839 bi.bV5Height = - (LONG)pEvent->height(); 2840 bi.bV5Planes = 1; 2841 bi.bV5BitCount = 32; 2842 bi.bV5Compression = BI_BITFIELDS; 2843 bi.bV5RedMask = 0x00FF0000; 2844 bi.bV5GreenMask = 0x0000FF00; 2845 bi.bV5BlueMask = 0x000000FF; 2846 if (pEvent->hasAlpha()) 2847 bi.bV5AlphaMask = 0xFF000000; 2848 else 2849 bi.bV5AlphaMask = 0; 2850 2851 HDC hdc = GetDC(NULL); 2852 2853 // create the DIB section with an alpha channel 2854 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0); 2855 2856 ReleaseDC(NULL, hdc); 2857 2858 HBITMAP hMonoBitmap = NULL; 2859 if (pEvent->hasAlpha()) 2860 { 2861 // create an empty mask bitmap 2862 hMonoBitmap = CreateBitmap(pEvent->width(), pEvent->height(), 1, 1, NULL); 2863 } 2864 else 2865 { 2866 /* Word aligned AND mask. Will be allocated and created if necessary. */ 2867 uint8_t *pu8AndMaskWordAligned = NULL; 2868 2869 /* Width in bytes of the original AND mask scan line. */ 2870 uint32_t cbAndMaskScan = (pEvent->width() + 7) / 8; 2871 2872 if (cbAndMaskScan & 1) 2873 { 2874 /* Original AND mask is not word aligned. */ 2875 2876 /* Allocate memory for aligned AND mask. */ 2877 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * pEvent->height()); 2878 2879 Assert(pu8AndMaskWordAligned); 2880 2881 if (pu8AndMaskWordAligned) 2850 BITMAPV5HEADER bi; 2851 HBITMAP hBitmap; 2852 void *lpBits; 2853 2854 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER)); 2855 bi.bV5Size = sizeof(BITMAPV5HEADER); 2856 bi.bV5Width = uWidth; 2857 bi.bV5Height = - (LONG)uHeight; 2858 bi.bV5Planes = 1; 2859 bi.bV5BitCount = 32; 2860 bi.bV5Compression = BI_BITFIELDS; 2861 bi.bV5RedMask = 0x00FF0000; 2862 bi.bV5GreenMask = 0x0000FF00; 2863 bi.bV5BlueMask = 0x000000FF; 2864 if (fHasAlpha) 2865 bi.bV5AlphaMask = 0xFF000000; 2866 else 2867 bi.bV5AlphaMask = 0; 2868 2869 HDC hdc = GetDC(NULL); 2870 2871 /* Create the DIB section with an alpha channel: */ 2872 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0); 2873 2874 ReleaseDC(NULL, hdc); 2875 2876 HBITMAP hMonoBitmap = NULL; 2877 if (fHasAlpha) 2878 { 2879 /* Create an empty mask bitmap: */ 2880 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL); 2881 } 2882 else 2883 { 2884 /* Word aligned AND mask. Will be allocated and created if necessary. */ 2885 uint8_t *pu8AndMaskWordAligned = NULL; 2886 2887 /* Width in bytes of the original AND mask scan line. */ 2888 uint32_t cbAndMaskScan = (uWidth + 7) / 8; 2889 2890 if (cbAndMaskScan & 1) 2891 { 2892 /* Original AND mask is not word aligned. */ 2893 2894 /* Allocate memory for aligned AND mask. */ 2895 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight); 2896 2897 Assert(pu8AndMaskWordAligned); 2898 2899 if (pu8AndMaskWordAligned) 2900 { 2901 /* According to MSDN the padding bits must be 0. 2902 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */ 2903 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth; 2904 Assert(u32PaddingBits < 8); 2905 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 2906 2907 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 2908 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan)); 2909 2910 uint8_t *src = (uint8_t *)srcAndMaskPtr; 2911 uint8_t *dst = pu8AndMaskWordAligned; 2912 2913 unsigned i; 2914 for (i = 0; i < uHeight; i++) 2882 2915 { 2883 /* According to MSDN the padding bits must be 0. 2884 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */ 2885 uint32_t u32PaddingBits = cbAndMaskScan * 8 - pEvent->width(); 2886 Assert(u32PaddingBits < 8); 2887 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 2888 2889 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 2890 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, pEvent->width(), cbAndMaskScan)); 2891 2892 uint8_t *src = (uint8_t *)srcAndMaskPtr; 2893 uint8_t *dst = pu8AndMaskWordAligned; 2894 2895 unsigned i; 2896 for (i = 0; i < pEvent->height(); i++) 2916 memcpy(dst, src, cbAndMaskScan); 2917 2918 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; 2919 2920 src += cbAndMaskScan; 2921 dst += cbAndMaskScan + 1; 2922 } 2923 } 2924 } 2925 2926 /* Create the AND mask bitmap: */ 2927 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1, 2928 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 2929 2930 if (pu8AndMaskWordAligned) 2931 { 2932 RTMemTmpFree(pu8AndMaskWordAligned); 2933 } 2934 } 2935 2936 Assert(hBitmap); 2937 Assert(hMonoBitmap); 2938 if (hBitmap && hMonoBitmap) 2939 { 2940 DWORD *dstShapePtr = (DWORD *) lpBits; 2941 2942 for (uint y = 0; y < uHeight; y ++) 2943 { 2944 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan); 2945 srcShapePtr += srcShapePtrScan; 2946 dstShapePtr += uWidth; 2947 } 2948 2949 ICONINFO ii; 2950 ii.fIcon = FALSE; 2951 ii.xHotspot = uXHot; 2952 ii.yHotspot = uYHot; 2953 ii.hbmMask = hMonoBitmap; 2954 ii.hbmColor = hBitmap; 2955 2956 HCURSOR hAlphaCursor = CreateIconIndirect(&ii); 2957 Assert(hAlphaCursor); 2958 if (hAlphaCursor) 2959 { 2960 viewport()->setCursor(QCursor(hAlphaCursor)); 2961 ok = true; 2962 if (m_alphaCursor) 2963 DestroyIcon(m_alphaCursor); 2964 m_alphaCursor = hAlphaCursor; 2965 } 2966 } 2967 2968 if (hMonoBitmap) 2969 DeleteObject(hMonoBitmap); 2970 if (hBitmap) 2971 DeleteObject(hBitmap); 2972 2973 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 2974 2975 XcursorImage *img = XcursorImageCreate(uWidth, uHeight); 2976 Assert(img); 2977 if (img) 2978 { 2979 img->xhot = uXHot; 2980 img->yhot = uYHot; 2981 2982 XcursorPixel *dstShapePtr = img->pixels; 2983 2984 for (uint y = 0; y < uHeight; y ++) 2985 { 2986 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 2987 2988 if (!fHasAlpha) 2989 { 2990 /* Convert AND mask to the alpha channel: */ 2991 uchar byte = 0; 2992 for (uint x = 0; x < uWidth; x ++) 2993 { 2994 if (!(x % 8)) 2995 byte = *(srcAndMaskPtr ++); 2996 else 2997 byte <<= 1; 2998 2999 if (byte & 0x80) 2897 3000 { 2898 memcpy(dst, src, cbAndMaskScan); 2899 2900 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; 2901 2902 src += cbAndMaskScan; 2903 dst += cbAndMaskScan + 1; 3001 /* Linux doesn't support inverted pixels (XOR ops, 3002 * to be exact) in cursor shapes, so we detect such 3003 * pixels and always replace them with black ones to 3004 * make them visible at least over light colors */ 3005 if (dstShapePtr [x] & 0x00FFFFFF) 3006 dstShapePtr [x] = 0xFF000000; 3007 else 3008 dstShapePtr [x] = 0x00000000; 2904 3009 } 3010 else 3011 dstShapePtr [x] |= 0xFF000000; 2905 3012 } 2906 3013 } 2907 3014 2908 /* create the AND mask bitmap */ 2909 hMonoBitmap = ::CreateBitmap(pEvent->width(), pEvent->height(), 1, 1, 2910 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 2911 2912 if (pu8AndMaskWordAligned) 2913 { 2914 RTMemTmpFree(pu8AndMaskWordAligned); 2915 } 2916 } 2917 2918 Assert(hBitmap); 2919 Assert(hMonoBitmap); 2920 if (hBitmap && hMonoBitmap) 2921 { 2922 DWORD *dstShapePtr = (DWORD *) lpBits; 2923 2924 for (uint y = 0; y < pEvent->height(); y ++) 2925 { 2926 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan); 2927 srcShapePtr += srcShapePtrScan; 2928 dstShapePtr += pEvent->width(); 2929 } 2930 2931 ICONINFO ii; 2932 ii.fIcon = FALSE; 2933 ii.xHotspot = pEvent->xHot(); 2934 ii.yHotspot = pEvent->yHot(); 2935 ii.hbmMask = hMonoBitmap; 2936 ii.hbmColor = hBitmap; 2937 2938 HCURSOR hAlphaCursor = CreateIconIndirect(&ii); 2939 Assert(hAlphaCursor); 2940 if (hAlphaCursor) 2941 { 2942 viewport()->setCursor(QCursor(hAlphaCursor)); 2943 ok = true; 2944 if (mAlphaCursor) 2945 DestroyIcon(mAlphaCursor); 2946 mAlphaCursor = hAlphaCursor; 2947 } 2948 } 2949 2950 if (hMonoBitmap) 2951 DeleteObject(hMonoBitmap); 2952 if (hBitmap) 2953 DeleteObject(hBitmap); 2954 2955 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 2956 2957 XcursorImage *img = XcursorImageCreate (pEvent->width(), pEvent->height()); 2958 Assert (img); 2959 if (img) 2960 { 2961 img->xhot = pEvent->xHot(); 2962 img->yhot = pEvent->yHot(); 2963 2964 XcursorPixel *dstShapePtr = img->pixels; 2965 2966 for (uint y = 0; y < pEvent->height(); y ++) 2967 { 2968 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 2969 2970 if (!pEvent->hasAlpha()) 2971 { 2972 /* convert AND mask to the alpha channel */ 2973 uchar byte = 0; 2974 for (uint x = 0; x < pEvent->width(); x ++) 2975 { 2976 if (!(x % 8)) 2977 byte = *(srcAndMaskPtr ++); 2978 else 2979 byte <<= 1; 2980 2981 if (byte & 0x80) 2982 { 2983 /* Linux doesn't support inverted pixels (XOR ops, 2984 * to be exact) in cursor shapes, so we detect such 2985 * pixels and always replace them with black ones to 2986 * make them visible at least over light colors */ 2987 if (dstShapePtr [x] & 0x00FFFFFF) 2988 dstShapePtr [x] = 0xFF000000; 2989 else 2990 dstShapePtr [x] = 0x00000000; 2991 } 2992 else 2993 dstShapePtr [x] |= 0xFF000000; 2994 } 2995 } 2996 2997 srcShapePtr += srcShapePtrScan; 2998 dstShapePtr += pEvent->width(); 2999 } 3000 3001 Cursor cur = XcursorImageLoadCursor (QX11Info::display(), img); 3002 Assert (cur); 3003 if (cur) 3004 { 3005 viewport()->setCursor (QCursor (cur)); 3006 ok = true; 3007 } 3008 3009 XcursorImageDestroy (img); 3010 } 3015 srcShapePtr += srcShapePtrScan; 3016 dstShapePtr += uWidth; 3017 } 3018 3019 Cursor cur = XcursorImageLoadCursor(QX11Info::display(), img); 3020 Assert (cur); 3021 if (cur) 3022 { 3023 viewport()->setCursor(QCursor(cur)); 3024 ok = true; 3025 } 3026 3027 XcursorImageDestroy(img); 3028 } 3011 3029 3012 3030 #elif defined(Q_WS_MAC) 3013 3031 3014 /* Create a ARGB image out of the shape data. */ 3015 QImage image (pEvent->width(), pEvent->height(), QImage::Format_ARGB32); 3016 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 3017 unsigned cbSrcMaskLine = RT_ALIGN (pEvent->width(), 8) / 8; 3018 for (unsigned int y = 0; y < pEvent->height(); ++y) 3019 { 3020 for (unsigned int x = 0; x < pEvent->width(); ++x) 3021 { 3022 unsigned int color = ((unsigned int*)srcShapePtr)[y*pEvent->width()+x]; 3023 /* If the alpha channel isn't in the shape data, we have to 3024 * create them from the and-mask. This is a bit field where 1 3025 * represent transparency & 0 opaque respectively. */ 3026 if (!pEvent->hasAlpha()) 3032 /* Create a ARGB image out of the shape data. */ 3033 QImage image (uWidth, uHeight, QImage::Format_ARGB32); 3034 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 3035 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8; 3036 for (unsigned int y = 0; y < uHeight; ++y) 3037 { 3038 for (unsigned int x = 0; x < uWidth; ++x) 3039 { 3040 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x]; 3041 /* If the alpha channel isn't in the shape data, we have to 3042 * create them from the and-mask. This is a bit field where 1 3043 * represent transparency & 0 opaque respectively. */ 3044 if (!fHasAlpha) 3045 { 3046 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) 3047 color |= 0xff000000; 3048 else 3027 3049 { 3028 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) 3029 color |= 0xff000000; 3050 /* This isn't quite right, but it's the best we can do I think... */ 3051 if (color & 0x00ffffff) 3052 color = 0xff000000; 3030 3053 else 3031 { 3032 /* This isn't quite right, but it's the best we can do I 3033 * think... */ 3034 if (color & 0x00ffffff) 3035 color = 0xff000000; 3036 else 3037 color = 0x00000000; 3038 } 3054 color = 0x00000000; 3039 3055 } 3040 image.setPixel (x, y, color); 3041 } 3042 /* Move one scanline forward. */ 3043 pbSrcMask += cbSrcMaskLine; 3044 } 3045 /* Set the new cursor */ 3046 QCursor cursor (QPixmap::fromImage (image), pEvent->xHot(), pEvent->yHot()); 3047 viewport()->setCursor (cursor); 3048 ok = true; 3049 NOREF (srcShapePtrScan); 3056 } 3057 image.setPixel (x, y, color); 3058 } 3059 /* Move one scanline forward. */ 3060 pbSrcMask += cbSrcMaskLine; 3061 } 3062 /* Set the new cursor: */ 3063 QCursor cursor(QPixmap::fromImage(image), uXHot, uYHot); 3064 viewport()->setCursor(cursor); 3065 ok = true; 3066 NOREF(srcShapePtrScan); 3050 3067 3051 3068 #else … … 3055 3072 #endif 3056 3073 3057 if (ok) 3058 mLastCursor = viewport()->cursor(); 3059 else 3060 viewport()->unsetCursor(); 3061 } 3074 if (ok) 3075 m_lastCursor = viewport()->cursor(); 3062 3076 else 3063 { 3064 if (pEvent->isVisible()) 3065 { 3066 viewport()->setCursor(mLastCursor); 3067 } 3068 else 3069 { 3070 viewport()->setCursor(Qt::BlankCursor); 3071 } 3072 } 3073 mHideHostPointer = !pEvent->isVisible(); 3074 } 3075 #endif 3076 3077 inline QRgb qRgbIntensity(QRgb rgb, int mul, int div) 3078 { 3079 int r = qRed(rgb); 3080 int g = qGreen(rgb); 3081 int b = qBlue(rgb); 3082 return qRgb(mul * r / div, mul * g / div, mul * b / div); 3083 } 3084 3085 void UIMachineView::storeConsoleSize(int aWidth, int aHeight) 3086 { 3087 LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight)); 3088 mStoredConsoleSize = QRect(0, 0, aWidth, aHeight); 3077 viewport()->unsetCursor(); 3089 3078 } 3090 3079 … … 3093 3082 machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setChecked(false); 3094 3083 machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setEnabled(bDisabled); 3095 }3096 3097 void UIMachineView::setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight)3098 {3099 switch (aGeo)3100 {3101 case DesktopGeo_Fixed:3102 mDesktopGeo = DesktopGeo_Fixed;3103 if (aWidth != 0 && aHeight != 0)3104 mDesktopGeometry = QRect(0, 0, aWidth, aHeight);3105 else3106 mDesktopGeometry = QRect(0, 0, 0, 0);3107 storeConsoleSize(0, 0);3108 break;3109 case DesktopGeo_Automatic:3110 mDesktopGeo = DesktopGeo_Automatic;3111 mDesktopGeometry = QRect(0, 0, 0, 0);3112 storeConsoleSize(0, 0);3113 break;3114 case DesktopGeo_Any:3115 mDesktopGeo = DesktopGeo_Any;3116 mDesktopGeometry = QRect(0, 0, 0, 0);3117 break;3118 default:3119 AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo));3120 mDesktopGeo = DesktopGeo_Invalid;3121 }3122 }3123 3124 QRect UIMachineView::availableGeometry()3125 {3126 return machineWindowWrapper()->machineWindow()->isFullScreen() ?3127 QApplication::desktop()->screenGeometry(this) :3128 QApplication::desktop()->availableGeometry(this);3129 3084 } 3130 3085 … … 3167 3122 if (mDockIconEnabled) 3168 3123 { 3169 if (!m PausedShot.isNull())3170 { 3171 CGImageRef pauseImg = ::darwinToCGImageRef (&m PausedShot);3124 if (!m_pauseShot.isNull()) 3125 { 3126 CGImageRef pauseImg = ::darwinToCGImageRef (&m_pauseShot); 3172 3127 /* Use the pause image as background */ 3173 3128 mDockIconPreview->updateDockPreview (pauseImg); … … 3178 3133 # if defined (VBOX_GUI_USE_QUARTZ2D) 3179 3134 // TODO_NEW_CORE 3180 // if (mode == VBoxDefs::Quartz2DMode)3135 // if (mode() == VBoxDefs::Quartz2DMode) 3181 3136 // { 3182 3137 /* If the render mode is Quartz2D we could use the CGImageRef 3183 3138 * of the framebuffer for the dock icon creation. This saves 3184 3139 * some conversion time. */ 3185 // mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (m FrameBuf)->imageRef());3140 // mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (m_pFrameBuffer)->imageRef()); 3186 3141 // } 3187 3142 // else … … 3190 3145 * framebuffer */ 3191 3146 // TODO_NEW_CORE 3192 // mDockIconPreview->updateDockPreview (m FrameBuf);3147 // mDockIconPreview->updateDockPreview (m_pFrameBuffer); 3193 3148 } 3194 3149 } … … 3201 3156 * the overlay stuff only. */ 3202 3157 if (mDockIconEnabled && 3203 (m LastState == KMachineState_Running ||3204 m LastState == KMachineState_Paused ||3205 m LastState == KMachineState_Teleporting ||3206 m LastState == KMachineState_LiveSnapshotting ||3207 m LastState == KMachineState_Restoring ||3208 m LastState == KMachineState_TeleportingPausedVM ||3209 m LastState == KMachineState_TeleportingIn ||3210 m LastState == KMachineState_Saving))3158 (m_machineState == KMachineState_Running || 3159 m_machineState == KMachineState_Paused || 3160 m_machineState == KMachineState_Teleporting || 3161 m_machineState == KMachineState_LiveSnapshotting || 3162 m_machineState == KMachineState_Restoring || 3163 m_machineState == KMachineState_TeleportingPausedVM || 3164 m_machineState == KMachineState_TeleportingIn || 3165 m_machineState == KMachineState_Saving)) 3211 3166 updateDockIcon(); 3212 3167 else … … 3223 3178 the keyboard/mouse is grabbed (this is when we have a valid 3224 3179 event handler). */ 3225 if (aOn || m KeyboardGrabbed)3180 if (aOn || m_fKeyboardGrabbed) 3226 3181 ::darwinSetMouseCoalescingEnabled (aOn); 3227 3182 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h
r26752 r26754 40 40 #endif /* Q_WS_MAC */ 41 41 42 /* Local forward declarations */ 42 /* Local forwards */ 43 #ifdef Q_WS_MAC 43 44 class VBoxChangeDockIconUpdateEvent; 44 45 class VBoxChangePresentationModeEvent; 45 46 class VBoxDockIconPreview; 47 #endif /* Q_WS_MAC */ 46 48 47 49 class UIMachineView : public QAbstractScrollArea … … 59 61 , UIVisualStateType visualStateType); 60 62 63 /* Public virtual members: */ 64 virtual void normalizeGeometry(bool bAdjustPosition = false) = 0; 65 61 66 /* Public setters: */ 62 67 void setIgnoreGuestResize(bool bIgnore) { m_bIsGuestResizeIgnored = bIgnore; } 63 68 void setMouseIntegrationEnabled(bool bEnabled); 64 virtual void normalizeGeometry(bool bAdjustPosition = false) = 0;65 69 //void setMachineViewFinalized(bool fTrue = true) { m_bIsMachineWindowResizeIgnored = !fTrue; } 66 70 … … 70 74 void setMouseCoalescingEnabled(bool aOn); 71 75 void setDockIconEnabled(bool aOn) { mDockIconEnabled = aOn; }; 72 73 const QPixmap& pauseShot() const { return mPausedShot; }74 76 #endif 75 77 76 78 signals: 77 79 78 /* M achine viewsignals: */80 /* Mouse/Keyboard state-change signals: */ 79 81 void keyboardStateChanged(int iState); 80 82 void mouseStateChanged(int iState); … … 97 99 ); 98 100 virtual ~UIMachineView(); 101 102 /* Desktop geometry types: */ 103 enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any }; 99 104 100 105 /* Protected getters: */ … … 102 107 CConsole &console() { return m_console; } 103 108 104 /* Protected members: */ 109 /* Protected getters: */ 110 VBoxDefs::RenderMode mode() const { return m_mode; } 105 111 QSize sizeHint() const; 106 112 int contentsX() const; … … 110 116 int visibleWidth() const; 111 117 int visibleHeight() const; 118 QRect desktopGeometry() const; 119 bool isGuestSupportsGraphics() const { return m_bIsGuestSupportsGraphics; } 120 const QPixmap& pauseShot() const { return m_pauseShot; } 121 //bool isMouseAbsolute() const { return m_bIsMouseAbsolute; } 122 123 /* Protected members: */ 112 124 void calculateDesktopGeometry(); 113 QRect desktopGeometry() const; 114 //bool isMouseAbsolute() const { return m_bIsMouseAbsolute; } 125 void setDesktopGeometry(DesktopGeo geometry, int iWidth, int iHeight); 126 void storeConsoleSize(int iWidth, int iHeight); 127 QRect availableGeometry(); 128 virtual void maybeRestrictMinimumSize() = 0; 115 129 116 130 /* Prepare routines: */ 117 void prepareFrameBuffer(); 118 void prepareCommon(); 119 void prepareFilters(); 120 void loadMachineViewSettings(); 131 virtual void prepareFrameBuffer(); 132 virtual void prepareCommon(); 133 virtual void prepareFilters(); 134 virtual void prepareConsoleConnections(); 135 virtual void loadMachineViewSettings(); 121 136 122 137 /* Cleanup routines: */ 123 //void saveMachineViewSettings(); 124 //void cleanupFilters(); 125 void cleanupCommon(); 126 void cleanupFrameBuffer(); 127 128 /* Protected variables: */ 129 VBoxDefs::RenderMode mode; 130 bool m_bIsGuestSupportsGraphics : 1; 138 //virtual void saveMachineViewSettings(); 139 //virtual void cleanupConsoleConnections(); 140 //virtual void cleanupFilters(); 141 virtual void cleanupCommon(); 142 virtual void cleanupFrameBuffer(); 131 143 132 144 private slots: 145 146 void sltMousePointerShapeChange(bool fIsVisible, bool fHasAlpha, 147 uint uXHot, uint uYHot, uint uWidth, uint uHeight, 148 const uchar *pShapeData); 149 void sltMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor); 150 void sltKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock); 151 void sltStateChange(KMachineState state); 152 void sltAdditionsStateChange(); 133 153 134 154 #ifdef Q_WS_MAC … … 143 163 private: 144 164 145 /* Event processors: */165 /* Cross-platforms event processors: */ 146 166 bool event(QEvent *pEvent); 147 167 bool eventFilter(QObject *pWatched, QEvent *pEvent); 168 void focusEvent(bool aHasFocus, bool aReleaseHostKey = true); 169 bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL); 170 bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos, 171 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 172 int aWheelDelta, Qt::Orientation aWheelDir); 173 void resizeEvent(QResizeEvent *pEvent); 174 void moveEvent(QMoveEvent *pEvent); 175 void paintEvent(QPaintEvent *pEvent); 176 177 /* Platform specific event processors: */ 148 178 #if defined(Q_WS_WIN32) 179 static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); 149 180 bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event); 150 181 bool winEvent(MSG *aMsg, long *aResult); … … 156 187 bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent); 157 188 void darwinGrabKeyboardEvents(bool fGrab); 158 #endif159 #if defined (Q_WS_WIN32)160 static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);161 #elif defined (Q_WS_MAC)162 189 # ifdef QT_MAC_USE_COCOA 163 190 static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); … … 167 194 #endif 168 195 169 /* Flags for keyEvent() */ 170 enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 }; 171 void emitKeyboardStateChanged() 172 { 173 emit keyboardStateChanged((m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) | 174 (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0)); 175 } 176 void emitMouseStateChanged() 177 { 178 emit mouseStateChanged((m_bIsMouseCaptured ? UIMouseStateType_MouseCaptured : 0) | 179 (m_bIsMouseAbsolute ? UIMouseStateType_MouseAbsolute : 0) | 180 (!m_bIsMouseIntegrated ? UIMouseStateType_MouseAbsoluteDisabled : 0)); 181 } 182 183 void focusEvent(bool aHasFocus, bool aReleaseHostKey = true); 184 bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL); 185 bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos, 186 Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers, 187 int aWheelDelta, Qt::Orientation aWheelDir); 188 void resizeEvent(QResizeEvent *pEvent); 189 void moveEvent(QMoveEvent *pEvent); 190 void paintEvent(QPaintEvent *pEvent); 191 192 /* Private members: */ 193 bool shouldHideHostPointer() const { return m_bIsMouseCaptured || (m_bIsMouseAbsolute && mHideHostPointer); } 194 bool isRunning() { return mLastState == KMachineState_Running || mLastState == KMachineState_Teleporting || mLastState == KMachineState_LiveSnapshotting; } 196 /* Private helpers: */ 195 197 void fixModifierState(LONG *piCodes, uint *puCount); 196 void scrollBy(int dx, int dy);197 198 QPoint viewportToContents(const QPoint &vp) const; 198 199 void updateSliders(); 200 void scrollBy(int dx, int dy); 199 201 #ifdef VBOX_WITH_VIDEOHWACCEL 200 202 void scrollContentsBy(int dx, int dy); 201 203 #endif 202 void onStateChange(KMachineState state); 203 void captureKbd(bool aCapture, bool aEmitSignal = true); 204 void captureMouse(bool aCapture, bool aEmitSignal = true); 204 void emitKeyboardStateChanged(); 205 void emitMouseStateChanged(); 206 void captureKbd(bool fCapture, bool fEmitSignal = true); 207 void captureMouse(bool fCapture, bool fEmitSignal = true); 208 void saveKeyStates(); 205 209 bool processHotKey(const QKeySequence &key, const QList<QAction*> &data); 206 210 void releaseAllPressedKeys(bool aReleaseHostKey = true); 207 void saveKeyStates();208 211 void sendChangedKeyStates(); 209 212 void updateMouseClipping(); 210 //void setPointerShape(MousePointerChangeEvent *pEvent); 211 212 enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any }; 213 void storeConsoleSize(int aWidth, int aHeight); 214 void setMouseIntegrationLocked(bool bDisabled); 215 void setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight); 216 virtual void maybeRestrictMinimumSize() = 0; 217 QRect availableGeometry(); 213 void setPointerShape(const uchar *pShapeData, bool fHasAlpha, 214 uint uXHot, uint uYHot, uint uWidth, uint uHeight); 215 void setMouseIntegrationLocked(bool fDisabled); 216 217 /* Private getters: */ 218 bool isRunning() { return m_machineState == KMachineState_Running || m_machineState == KMachineState_Teleporting || m_machineState == KMachineState_LiveSnapshotting; } 219 bool shouldHideHostPointer() const { return m_bIsMouseCaptured || (m_bIsMouseAbsolute && m_fHideHostPointer); } 218 220 219 221 static void dimImage(QImage &img); … … 222 224 UIMachineWindow *m_pMachineWindow; 223 225 CConsole m_console; 226 VBoxDefs::RenderMode m_mode; 224 227 const VBoxGlobalSettings &m_globalSettings; 225 KMachineState mLastState; 226 227 QPoint mLastPos; 228 QPoint mCapturedPos; 228 KMachineState m_machineState; 229 UIFrameBuffer *m_pFrameBuffer; 230 231 QCursor m_lastCursor; 232 #if defined(Q_WS_WIN) 233 HCURSOR m_alphaCursor; 234 #endif 235 QPoint m_lastMousePos; 236 QPoint m_capturedMousePos; 229 237 int m_iLastMouseWheelDelta; 230 238 231 enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 }; 232 uint8_t mPressedKeys[128]; 233 uint8_t mPressedKeysCopy[128]; 234 235 long muNumLockAdaptionCnt; 236 long muCapsLockAdaptionCnt; 239 uint8_t m_pressedKeys[128]; 240 uint8_t m_pressedKeysCopy[128]; 241 242 long m_uNumLockAdaptionCnt; 243 long m_uCapsLockAdaptionCnt; 237 244 238 245 bool m_bIsAutoCaptureDisabled : 1; … … 243 250 bool m_bIsHostkeyPressed : 1; 244 251 bool m_bIsHostkeyAlone : 1; 245 bool hostkey_in_capture : 1; 252 bool m_bHostkeyInCapture : 1; 253 bool m_bIsGuestSupportsGraphics : 1; 246 254 bool m_bIsMachineWindowResizeIgnored : 1; 247 255 bool m_bIsFrameBufferResizeIgnored : 1; 248 256 bool m_bIsGuestResizeIgnored : 1; 257 bool m_numLock : 1; 258 bool m_scrollLock : 1; 259 bool m_capsLock : 1; 260 bool m_fPassCAD; 261 bool m_fHideHostPointer; 262 #ifdef VBOX_WITH_VIDEOHWACCEL 263 bool m_fAccelerate2DVideo; 264 #endif 265 #if 0 // TODO: Do we need this flag? 249 266 bool mDoResize : 1; 250 bool mNumLock : 1;251 bool mScrollLock : 1;252 bool mCapsLock : 1;253 254 #ifdef VBOX_WITH_VIDEOHWACCEL255 bool mAccelerate2DVideo;256 #endif257 258 #if defined(Q_WS_WIN)259 HCURSOR mAlphaCursor;260 267 #endif 261 268 … … 263 270 # ifndef QT_MAC_USE_COCOA 264 271 /** Event handler reference. NULL if the handler isn't installed. */ 265 EventHandlerRef m DarwinEventHandlerRef;272 EventHandlerRef m_darwinEventHandlerRef; 266 273 # endif /* !QT_MAC_USE_COCOA */ 267 274 /** The current modifier key mask. Used to figure out which modifier 268 275 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 269 UInt32 mDarwinKeyModifiers; 270 bool mKeyboardGrabbed; 271 #endif 272 273 UIFrameBuffer *mFrameBuf; 274 275 QPixmap mPausedShot; 276 UInt32 m_darwinKeyModifiers; 277 bool m_fKeyboardGrabbed; 278 #endif 279 280 QPixmap m_pauseShot; 276 281 #if defined(Q_WS_MAC) 277 282 # if !defined (QT_MAC_USE_COCOA) … … 281 286 bool mDockIconEnabled; 282 287 #endif 283 DesktopGeo mDesktopGeo; 284 QRect mDesktopGeometry; 285 QRect mStoredConsoleSize; 286 bool mPassCAD; 287 bool mHideHostPointer; 288 QCursor mLastCursor; 288 DesktopGeo m_desktopGeometryType; 289 QRect m_desktopGeometry; 290 QRect m_storedConsoleSize; 289 291 290 292 /* Friend classes: */ 291 293 friend class UIFrameBuffer; 292 294 friend class UIFrameBufferQImage; 295 friend class UIFrameBufferQuartz2D; 293 296 }; 294 297 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r26709 r26754 537 537 case UIConsoleEventType_MousePointerShapeChange: 538 538 { 539 #if 0 // TODO: Move to machine view!540 MousePointerChangeEvent *me = (MousePointerChangeEvent*)pEvent;541 /* Change cursor shape only when mouse integration is542 * supported (change mouse shape type event may arrive after543 * mouse capability change that disables integration. */544 if (m_bIsMouseAbsolute)545 setPointerShape (me);546 else547 /* Note: actually we should still remember the requested548 * cursor shape. If we can't do that, at least remember549 * the requested visiblilty. */550 mHideHostPointer = !me->isVisible();551 #endif552 539 UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent); 553 540 emit sigMousePointerShapeChange(pConsoleEvent->isVisible(), pConsoleEvent->hasAlpha(), … … 560 547 case UIConsoleEventType_MouseCapabilityChange: 561 548 { 562 #if 0 // TODO: Move to machine view!563 MouseCapabilityEvent *me = (MouseCapabilityEvent*)pEvent;564 if (m_bIsMouseAbsolute != me->supportsAbsolute())565 {566 m_bIsMouseAbsolute = me->supportsAbsolute();567 /* correct the mouse capture state and reset the cursor568 * to the default shape if necessary */569 if (m_bIsMouseAbsolute)570 {571 CMouse mouse = m_console.GetMouse();572 mouse.PutMouseEventAbsolute (-1, -1, 0,573 0 /* Horizontal wheel */,574 0);575 captureMouse (false, false);576 }577 else578 viewport()->unsetCursor();579 emitMouseStateChanged();580 vboxProblem().remindAboutMouseIntegration (m_bIsMouseAbsolute);581 }582 if (me->needsHostCursor())583 setMouseIntegrationLocked (false);584 else585 setMouseIntegrationLocked (true);586 return true;587 #endif588 549 UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent); 589 550 emit sigMouseCapabilityChange(pConsoleEvent->supportsAbsolute(), pConsoleEvent->needsHostCursor()); … … 593 554 case UIConsoleEventType_KeyboardLedsChange: 594 555 { 595 #if 0 // TODO: Move to machine view!596 ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )pEvent;597 if (me->numLock() != mNumLock)598 muNumLockAdaptionCnt = 2;599 if (me->capsLock() != mCapsLock)600 muCapsLockAdaptionCnt = 2;601 mNumLock = me->numLock();602 mCapsLock = me->capsLock();603 mScrollLock = me->scrollLock();604 #endif605 556 UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent); 606 557 emit sigKeyboardLedsChange(pConsoleEvent->numLock(), pConsoleEvent->capsLock(), pConsoleEvent->scrollLock()); … … 610 561 case UIConsoleEventType_StateChange: 611 562 { 612 #if 0 // TODO: Move to machine view!613 MachineUIStateChangeEvent *me = (MachineUIStateChangeEvent *) pEvent;614 LogFlowFunc (("MachineUIStateChangeEventType: state=%d\n",615 me->machineState()));616 onStateChange (me->machineState());617 emit machineStateChanged (me->machineState());618 #endif619 563 UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent); 620 564 emit sigStateChange(pConsoleEvent->machineState()); … … 624 568 case UIConsoleEventType_AdditionsStateChange: 625 569 { 626 #if 0 // TODO: Move to machine view!627 GuestAdditionsChangeEvent *ge = (GuestAdditionsChangeEvent *) pEvent;628 LogFlowFunc (("UIAdditionsStateChangeEventType\n"));629 /* Always send a size hint if we are in fullscreen or seamless630 * when the graphics capability is enabled, in case the host631 * resolution has changed since the VM was last run. */632 #if 0633 if (!mDoResize && !m_bIsGuestSupportsGraphics &&634 ge->supportsGraphics() &&635 (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))636 mDoResize = true;637 #endif638 m_bIsGuestSupportsGraphics = ge->supportsGraphics();639 640 maybeRestrictMinimumSize();641 642 #if 0643 /* This will only be acted upon if mDoResize is true. */644 doResizeHint();645 #endif646 647 emit additionsStateChanged (ge->additionVersion(),648 ge->additionActive(),649 ge->supportsSeamless(),650 ge->supportsGraphics());651 #endif652 570 emit sigAdditionsStateChange(); 653 571 return true; … … 656 574 case UIConsoleEventType_NetworkAdapterChange: 657 575 { 658 #if 0 // TODO: Move to machine view!659 /* no specific adapter information stored in this660 * event is currently used */661 emit networkStateChange();662 #endif663 576 UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent); 664 577 emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter()); … … 688 601 case UIConsoleEventType_MediumChange: 689 602 { 690 #if 0 // TODO: Move to machine view!691 MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) pEvent;692 LogFlowFunc (("MediaChangeEvent\n"));693 694 emit mediaDriveChanged (mce->type());695 #endif696 603 UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent); 697 604 emit sigMediumChange(pConsoleEvent->mediumAttahment()); … … 726 633 case UIConsoleEventType_USBDeviceStateChange: 727 634 { 728 #if 0 // TODO: Move to machine view!729 UIUSBDeviceUIStateChangeEvent *ue = (UIUSBDeviceUIStateChangeEvent *)pEvent;730 731 bool success = ue->error().isNull();732 733 if (!success)734 {735 if (ue->attached())736 vboxProblem().cannotAttachUSBDevice (737 m_console,738 vboxGlobal().details (ue->device()), ue->error());739 else740 vboxProblem().cannotDetachUSBDevice (741 m_console,742 vboxGlobal().details (ue->device()), ue->error());743 }744 745 emit usbStateChange();746 #endif747 635 UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent); 748 636 emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error()); … … 758 646 case UIConsoleEventType_RuntimeError: 759 647 { 760 #if 0 // TODO: Move to machine view!761 UIRuntimeErrorEvent *pConsoleEvent = (UIRuntimeErrorEvent *) pEvent;762 vboxProblem().showRuntimeError(m_console, ee->fatal(), ee->errorID(), ee->message());763 #endif764 648 UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent); 765 649 emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message()); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
r26709 r26754 75 75 76 76 /* Console signals: */ 77 void sigMousePointerShapeChange(bool bIsVisible, bool bHasAlpha, bool uXHot, bool uYHot, bool uWidth, booluHeight, const uchar *pShapeData);77 void sigMousePointerShapeChange(bool bIsVisible, bool bHasAlpha, uint uXHot, uint uYHot, uint uWidth, uint uHeight, const uchar *pShapeData); 78 78 void sigMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor); 79 79 void sigKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock); … … 91 91 void sigUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error); 92 92 void sigSharedFolderChange(); 93 void sigRuntimeError(bool bIsFatal, QString strErrorId, QStringstrMessage);93 void sigRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage); 94 94 95 95 private: -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp
r26730 r26754 25 25 #include <QApplication> 26 26 #include <QDesktopWidget> 27 #include <QMainWindow> 28 #include <QMenuBar> 27 29 28 30 /* Local includes */ … … 54 56 /* Prepare event-filters: */ 55 57 prepareFilters(); 58 59 /* Prepare console connections: */ 60 prepareConsoleConnections(); 56 61 57 62 /* Load machine view settings: */ … … 104 109 ar = dwt->availableGeometry(pTopLevelWidget->pos()); 105 110 106 fr = VBoxGlobal::normalizeGeometry(fr, ar, mode != VBoxDefs::SDLMode /* canResize */);111 fr = VBoxGlobal::normalizeGeometry(fr, ar, mode() != VBoxDefs::SDLMode /* canResize */); 107 112 } 108 113 … … 122 127 * We need to do that because we cannot correctly draw in a scrolled window in SDL mode. 123 128 * In all other modes, or when auto-resize is in force, this function does nothing. */ 124 if (mode == VBoxDefs::SDLMode)125 { 126 if (! m_bIsGuestSupportsGraphics|| !m_bIsGuestAutoresizeEnabled)129 if (mode() == VBoxDefs::SDLMode) 130 { 131 if (!isGuestSupportsGraphics() || !m_bIsGuestAutoresizeEnabled) 127 132 setMinimumSize(sizeHint()); 128 133 else … … 134 139 { 135 140 #if 0 // TODO: fix that logic! 136 if ( m_bIsGuestSupportsGraphics&& m_bIsGuestAutoresizeEnabled)141 if (isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled) 137 142 { 138 143 /* If this slot is invoked directly then use the passed size … … 180 185 maybeRestrictMinimumSize(); 181 186 182 if ( m_bIsGuestSupportsGraphics&& m_bIsGuestAutoresizeEnabled)187 if (isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled) 183 188 doResizeHint(); 184 189 } … … 192 197 } 193 198 199 void UIMachineViewNormal::prepareFilters() 200 { 201 /* Parent class filters: */ 202 UIMachineView::prepareFilters(); 203 204 /* Normal window filters: */ 205 qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this); 206 } 207 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.h
r26730 r26754 57 57 private: 58 58 59 /* Prepare routines: */ 60 void prepareFilters(); 61 59 62 bool m_bIsGuestAutoresizeEnabled : 1; 60 63
Note:
See TracChangeset
for help on using the changeset viewer.