VirtualBox

Changeset 97847 in vbox for trunk


Ignore:
Timestamp:
Dec 20, 2022 2:59:14 PM (2 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9898: Migrating UIMiniToolBar bits to Qt6.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp

    r97682 r97847  
    559559    setMask(m_pToolbar->geometry());
    560560#endif /* VBOX_WS_WIN || VBOX_WS_X11 */
    561 }
    562 
    563 void UIMiniToolBar::sltHandleToolbarResize()
    564 {
    565     /* Adjust geometry: */
    566     adjustGeometry();
    567 }
    568 
    569 void UIMiniToolBar::sltAutoHideToggled()
    570 {
    571     /* Propagate from child: */
    572     setAutoHide(m_pToolbar->autoHide(), false);
    573     emit sigAutoHideToggled(m_pToolbar->autoHide());
    574 }
    575 
    576 void UIMiniToolBar::sltHoverEnter()
    577 {
    578     /* Mark as 'hovered' if necessary: */
    579     if (!m_fHovered)
    580     {
    581         m_fHovered = true;
    582         emit sigHoverEnter();
    583     }
    584 }
    585 
    586 void UIMiniToolBar::sltHoverLeave()
    587 {
    588     /* Mark as 'unhovered' if necessary: */
    589     if (m_fHovered)
    590     {
    591         m_fHovered = false;
    592         if (m_fAutoHide)
    593             emit sigHoverLeave();
    594     }
    595 }
    596 
    597 void UIMiniToolBar::sltCheckWindowActivationSanity()
    598 {
    599     /* Do nothing if parent window is already active: */
    600     if (   m_pParent
    601         && QGuiApplication::focusWindow() == m_pParent->windowHandle())
    602         return;
    603 
    604     /* We can't touch window activation if have modal or popup
    605      * window opened, otherwise internal Qt state get flawed: */
    606     if (   QApplication::activeModalWidget()
    607         || QApplication::activePopupWidget())
    608     {
    609         /* But we should recheck the state in let's say 300ms: */
    610         QTimer::singleShot(300, this, SLOT(sltCheckWindowActivationSanity()));
    611         return;
    612     }
    613 
    614     /* Notify listener about we have stole window activation: */
    615     emit sigNotifyAboutWindowActivationStolen();
    616 }
    617 
    618 void UIMiniToolBar::sltHide()
    619 {
    620     LogRel(("GUI: Hide mini-toolbar for window #%d\n", m_iWindowIndex));
    621 
    622 #if defined(VBOX_WS_MAC)
    623 
    624     // Nothing
    625 
    626 #elif defined(VBOX_WS_WIN)
    627 
    628     /* Reset window state to NONE and hide it: */
    629     setWindowState(Qt::WindowNoState);
    630     hide();
    631 
    632 #elif defined(VBOX_WS_X11)
    633 
    634     /* Just hide window: */
    635     hide();
    636 
    637 #else
    638 
    639 # warning "port me"
    640 
    641 #endif
    642 }
    643 
    644 void UIMiniToolBar::sltShow()
    645 {
    646     LogRel(("GUI: Show mini-toolbar for window #%d\n", m_iWindowIndex));
    647 
    648     /* Update transience: */
    649     sltAdjustTransience();
    650 
    651 #if defined(VBOX_WS_MAC)
    652 
    653     // Nothing
    654 
    655 #elif defined(VBOX_WS_WIN)
    656 
    657     // WORKAROUND:
    658     // If the host-screen is changed => we should
    659     // reset window state to NONE first because
    660     // we need an expose on showFullScreen call.
    661     if (m_geometryType == GeometryType_Full)
    662         setWindowState(Qt::WindowNoState);
    663 
    664     /* Adjust window: */
    665     sltAdjust();
    666     /* Show window in necessary mode: */
    667     switch (m_geometryType)
    668     {
    669         case GeometryType_Available:
    670         {
    671             /* Show normal: */
    672             show();
    673             break;
    674         }
    675         case GeometryType_Full:
    676         {
    677             /* Show full-screen: */
    678             showFullScreen();
    679             break;
    680         }
    681     }
    682 
    683 #elif defined(VBOX_WS_X11)
    684 
    685     /* Show window in necessary mode: */
    686     switch (m_geometryType)
    687     {
    688         case GeometryType_Available:
    689         {
    690             /* Adjust window: */
    691             sltAdjust();
    692             /* Show maximized: */
    693             if (!isMaximized())
    694                 showMaximized();
    695             break;
    696         }
    697         case GeometryType_Full:
    698         {
    699             /* Show full-screen: */
    700             showFullScreen();
    701             /* Adjust window: */
    702             sltAdjust();
    703             break;
    704         }
    705     }
    706 
    707 #else
    708 
    709 # warning "port me"
    710 
    711 #endif
    712 
    713     /* Simulate toolbar auto-hiding: */
    714     simulateToolbarAutoHiding();
    715 }
    716 
    717 void UIMiniToolBar::sltAdjust()
    718 {
    719     LogRel(("GUI: Adjust mini-toolbar for window #%d\n", m_iWindowIndex));
    720 
    721     /* Get corresponding host-screen: */
    722     const int iHostScreenCount = UIDesktopWidgetWatchdog::screenCount();
    723     int iHostScreen = UIDesktopWidgetWatchdog::screenNumber(m_pParent);
    724     // WORKAROUND:
    725     // When switching host-screen count, especially in complex cases where RDP client is "replacing" host-screen(s) with own virtual-screen(s),
    726     // Qt could behave quite arbitrary and laggy, and due to racing there could be a situation when QDesktopWidget::screenNumber() returns -1
    727     // as a host-screen number where the parent window is currently located. We should handle this situation anyway, so let's assume the parent
    728     // window is located on primary (0) host-screen if it's present or ignore this request at all.
    729     if (iHostScreen < 0 || iHostScreen >= iHostScreenCount)
    730     {
    731         if (iHostScreenCount > 0)
    732         {
    733             LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Fallback to primary.\n", m_iWindowIndex, iHostScreen));
    734             iHostScreen = 0;
    735         }
    736         else
    737         {
    738             LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Ignore request.\n", m_iWindowIndex, iHostScreen));
    739             return;
    740         }
    741     }
    742 
    743     /* Get corresponding working area: */
    744     QRect workingArea;
    745     switch (m_geometryType)
    746     {
    747         case GeometryType_Available: workingArea = gpDesktop->availableGeometry(iHostScreen); break;
    748         case GeometryType_Full:      workingArea = gpDesktop->screenGeometry(iHostScreen); break;
    749     }
    750     Q_UNUSED(workingArea);
    751 
    752 #if defined(VBOX_WS_MAC)
    753 
    754     // Nothing
    755 
    756 #elif defined(VBOX_WS_WIN)
    757 
    758     switch (m_geometryType)
    759     {
    760         case GeometryType_Available:
    761         {
    762             /* Set appropriate window size: */
    763             const QSize newSize = workingArea.size();
    764             LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
    765                      m_iWindowIndex, newSize.width(), newSize.height()));
    766             resize(newSize);
    767 
    768             /* Move window onto required screen: */
    769             const QPoint newPosition = workingArea.topLeft();
    770             LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
    771                      m_iWindowIndex, newPosition.x(), newPosition.y()));
    772             move(newPosition);
    773 
    774             break;
    775         }
    776         case GeometryType_Full:
    777         {
    778             /* Map window onto required screen: */
    779             LogRel(("GUI:  Map mini-toolbar for window #%d to screen %d of %d\n",
    780                      m_iWindowIndex, iHostScreen, qApp->screens().size()));
    781             windowHandle()->setScreen(qApp->screens().at(iHostScreen));
    782 
    783             /* Set appropriate window size: */
    784             const QSize newSize = workingArea.size();
    785             LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
    786                      m_iWindowIndex, newSize.width(), newSize.height()));
    787             resize(newSize);
    788 
    789             break;
    790         }
    791     }
    792 
    793 #elif defined(VBOX_WS_X11)
    794 
    795     switch (m_geometryType)
    796     {
    797         case GeometryType_Available:
    798         {
    799             /* Make sure we are located on corresponding host-screen: */
    800             if (   UIDesktopWidgetWatchdog::screenCount() > 1
    801                 && (x() != workingArea.x() || y() != workingArea.y()))
    802             {
    803                 // WORKAROUND:
    804                 // With Qt5 on KDE we can't just move the window onto desired host-screen if
    805                 // window is maximized. So we have to show it normal first of all:
    806                 if (isVisible() && isMaximized())
    807                     showNormal();
    808 
    809                 // WORKAROUND:
    810                 // With Qt5 on X11 we can't just move the window onto desired host-screen if
    811                 // window size is more than the available geometry (working area) of that
    812                 // host-screen. So we are resizing it to a smaller size first of all:
    813                 const QSize newSize = workingArea.size() * .9;
    814                 LogRel(("GUI:  Resize mini-toolbar for window #%d to smaller size %dx%d\n",
    815                         m_iWindowIndex, newSize.width(), newSize.height()));
    816                 resize(newSize);
    817 
    818                 /* Move window onto required screen: */
    819                 const QPoint newPosition = workingArea.topLeft();
    820                 LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
    821                         m_iWindowIndex, newPosition.x(), newPosition.y()));
    822                 move(newPosition);
    823             }
    824 
    825             break;
    826         }
    827         case GeometryType_Full:
    828         {
    829             /* Determine whether we should use the native full-screen mode: */
    830             const bool fUseNativeFullScreen =    NativeWindowSubsystem::X11SupportsFullScreenMonitorsProtocol()
    831                                               && !gEDataManager->legacyFullscreenModeRequested();
    832             if (fUseNativeFullScreen)
    833             {
    834                 /* Tell recent window managers which host-screen this window should be mapped to: */
    835                 NativeWindowSubsystem::X11SetFullScreenMonitor(this, iHostScreen);
    836             }
    837 
    838             /* Set appropriate window size: */
    839             const QSize newSize = workingArea.size();
    840             LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
    841                     m_iWindowIndex, newSize.width(), newSize.height()));
    842             resize(newSize);
    843 
    844             /* Move window onto required screen: */
    845             const QPoint newPosition = workingArea.topLeft();
    846             LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
    847                     m_iWindowIndex, newPosition.x(), newPosition.y()));
    848             move(newPosition);
    849 
    850             /* Re-apply the full-screen state lost on above move(): */
    851             setWindowState(Qt::WindowFullScreen);
    852 
    853             break;
    854         }
    855     }
    856 
    857 #else
    858 
    859 # warning "port me"
    860 
    861 #endif
    862 }
    863 
    864 void UIMiniToolBar::sltAdjustTransience()
    865 {
    866     // WORKAROUND:
    867     // Make sure win id is generated,
    868     // else Qt5 can crash otherwise.
    869     winId();
    870     m_pParent->winId();
    871 
    872     /* Add the transience dependency: */
    873     windowHandle()->setTransientParent(m_pParent->windowHandle());
    874 }
    875 
    876 void UIMiniToolBar::prepare()
    877 {
    878     /* Install event-filters: */
    879     installEventFilter(this);
    880     m_pParent->installEventFilter(this);
    881 
    882 #if   defined(VBOX_WS_WIN)
    883     /* No background until first paint-event: */
    884     setAttribute(Qt::WA_NoSystemBackground);
    885     /* Enable translucency through Qt API: */
    886     setAttribute(Qt::WA_TranslucentBackground);
    887 #elif defined(VBOX_WS_X11)
    888     /* Enable translucency through Qt API if supported: */
    889     if (uiCommon().isCompositingManagerRunning())
    890         setAttribute(Qt::WA_TranslucentBackground);
    891 #endif /* VBOX_WS_X11 */
    892 
    893     /* Make sure we have no focus: */
    894     setFocusPolicy(Qt::NoFocus);
    895 
    896     /* Prepare area: */
    897     m_pArea = new QWidget;
    898     {
    899         /* Allow any area size: */
    900         m_pArea->setMinimumSize(QSize(1, 1));
    901         /* Configure own background: */
    902         QPalette pal = m_pArea->palette();
    903         pal.setColor(QPalette::Window, QColor(Qt::transparent));
    904         m_pArea->setPalette(pal);
    905         /* Layout area according parent-widget: */
    906         QVBoxLayout *pMainLayout = new QVBoxLayout(this);
    907         pMainLayout->setContentsMargins(0, 0, 0, 0);
    908         pMainLayout->addWidget(m_pArea);
    909         /* Make sure we have no focus: */
    910         m_pArea->setFocusPolicy(Qt::NoFocus);
    911     }
    912 
    913     /* Prepare mini-toolbar: */
    914     m_pToolbar = new UIMiniToolBarPrivate;
    915     {
    916         /* Make sure we have no focus: */
    917         m_pToolbar->setFocusPolicy(Qt::NoFocus);
    918         /* Propagate known options to child: */
    919         m_pToolbar->setAutoHide(m_fAutoHide);
    920         m_pToolbar->setAlignment(m_alignment);
    921         /* Configure own background: */
    922         QPalette pal = m_pToolbar->palette();
    923         pal.setColor(QPalette::Window, QApplication::palette().color(QPalette::Window));
    924         m_pToolbar->setPalette(pal);
    925         /* Configure child connections: */
    926         connect(m_pToolbar, &UIMiniToolBarPrivate::sigResized, this, &UIMiniToolBar::sltHandleToolbarResize);
    927         connect(m_pToolbar, &UIMiniToolBarPrivate::sigAutoHideToggled, this, &UIMiniToolBar::sltAutoHideToggled);
    928         connect(m_pToolbar, &UIMiniToolBarPrivate::sigMinimizeAction, this, &UIMiniToolBar::sigMinimizeAction);
    929         connect(m_pToolbar, &UIMiniToolBarPrivate::sigExitAction, this, &UIMiniToolBar::sigExitAction);
    930         connect(m_pToolbar, &UIMiniToolBarPrivate::sigCloseAction, this, &UIMiniToolBar::sigCloseAction);
    931         /* Add child to area: */
    932         m_pToolbar->setParent(m_pArea);
    933         /* Make sure we have no focus: */
    934         m_pToolbar->setFocusPolicy(Qt::NoFocus);
    935     }
    936 
    937     /* Prepare hover-enter/leave timers: */
    938     m_pHoverEnterTimer = new QTimer(this);
    939     {
    940         m_pHoverEnterTimer->setSingleShot(true);
    941         m_pHoverEnterTimer->setInterval(500);
    942         connect(m_pHoverEnterTimer, &QTimer::timeout, this, &UIMiniToolBar::sltHoverEnter);
    943     }
    944     m_pHoverLeaveTimer = new QTimer(this);
    945     {
    946         m_pHoverLeaveTimer->setSingleShot(true);
    947         m_pHoverLeaveTimer->setInterval(500);
    948         connect(m_pHoverLeaveTimer, &QTimer::timeout, this, &UIMiniToolBar::sltHoverLeave);
    949     }
    950 
    951     /* Install 'auto-hide' animation to 'toolbarPosition' property: */
    952     m_pAnimation = UIAnimation::installPropertyAnimation(this,
    953                                                          "toolbarPosition",
    954                                                          "hiddenToolbarPosition", "shownToolbarPosition",
    955                                                          SIGNAL(sigHoverEnter()), SIGNAL(sigHoverLeave()),
    956                                                          true);
    957 
    958     /* Adjust geometry first time: */
    959     adjustGeometry();
    960 
    961 #ifdef VBOX_WS_X11
    962     /* Hide mini-toolbar from taskbar and pager: */
    963     NativeWindowSubsystem::X11SetSkipTaskBarFlag(this);
    964     NativeWindowSubsystem::X11SetSkipPagerFlag(this);
    965 #endif
    966 }
    967 
    968 void UIMiniToolBar::cleanup()
    969 {
    970     /* Stop hover-enter/leave timers: */
    971     if (m_pHoverEnterTimer && m_pHoverEnterTimer->isActive())
    972         m_pHoverEnterTimer->stop();
    973     if (m_pHoverLeaveTimer && m_pHoverLeaveTimer->isActive())
    974         m_pHoverLeaveTimer->stop();
    975 
    976     /* Destroy animation before toolbar: */
    977     delete m_pAnimation;
    978     m_pAnimation = 0;
    979 
    980     /* Destroy toolbar after animation: */
    981     delete m_pToolbar;
    982     m_pToolbar = 0;
    983 }
    984 
    985 void UIMiniToolBar::enterEvent(QEvent*)
    986 {
    987     /* Stop the hover-leave timer if necessary: */
    988     if (m_pHoverLeaveTimer && m_pHoverLeaveTimer->isActive())
    989         m_pHoverLeaveTimer->stop();
    990 
    991     /* Start the hover-enter timer: */
    992     if (m_pHoverEnterTimer)
    993         m_pHoverEnterTimer->start();
    994 }
    995 
    996 void UIMiniToolBar::leaveEvent(QEvent*)
    997 {
    998     // WORKAROUND:
    999     // No idea why, but GUI receives mouse leave event
    1000     // when the mouse cursor is on the border of screen
    1001     // even if underlying widget is on the border of
    1002     // screen as well, we should detect and ignore that.
    1003     // Besides that, this is a good way to keep the
    1004     // tool-bar visible when the mouse moving through
    1005     // the desktop strut till the real screen border.
    1006     const QPoint cursorPosition = QCursor::pos();
    1007     if (   cursorPosition.y() <= y() + 1
    1008         || cursorPosition.y() >= y() + height() - 1)
    1009         return;
    1010 
    1011     /* Stop the hover-enter timer if necessary: */
    1012     if (m_pHoverEnterTimer && m_pHoverEnterTimer->isActive())
    1013         m_pHoverEnterTimer->stop();
    1014 
    1015     /* Start the hover-leave timer: */
    1016     if (m_fAutoHide && m_pHoverLeaveTimer)
    1017         m_pHoverLeaveTimer->start();
    1018 }
    1019 
    1020 void UIMiniToolBar::resizeEvent(QResizeEvent*)
    1021 {
    1022     /* Adjust geometry: */
    1023     adjustGeometry();
    1024561}
    1025562
     
    1167704}
    1168705
     706void UIMiniToolBar::resizeEvent(QResizeEvent*)
     707{
     708    /* Adjust geometry: */
     709    adjustGeometry();
     710}
     711
     712#ifdef VBOX_IS_QT6_OR_LATER
     713void UIMiniToolBar::enterEvent(QEnterEvent*)
     714#else
     715void UIMiniToolBar::enterEvent(QEvent*)
     716#endif
     717{
     718    /* Stop the hover-leave timer if necessary: */
     719    if (m_pHoverLeaveTimer && m_pHoverLeaveTimer->isActive())
     720        m_pHoverLeaveTimer->stop();
     721
     722    /* Start the hover-enter timer: */
     723    if (m_pHoverEnterTimer)
     724        m_pHoverEnterTimer->start();
     725}
     726
     727void UIMiniToolBar::leaveEvent(QEvent*)
     728{
     729    // WORKAROUND:
     730    // No idea why, but GUI receives mouse leave event
     731    // when the mouse cursor is on the border of screen
     732    // even if underlying widget is on the border of
     733    // screen as well, we should detect and ignore that.
     734    // Besides that, this is a good way to keep the
     735    // tool-bar visible when the mouse moving through
     736    // the desktop strut till the real screen border.
     737    const QPoint cursorPosition = QCursor::pos();
     738    if (   cursorPosition.y() <= y() + 1
     739        || cursorPosition.y() >= y() + height() - 1)
     740        return;
     741
     742    /* Stop the hover-enter timer if necessary: */
     743    if (m_pHoverEnterTimer && m_pHoverEnterTimer->isActive())
     744        m_pHoverEnterTimer->stop();
     745
     746    /* Start the hover-leave timer: */
     747    if (m_fAutoHide && m_pHoverLeaveTimer)
     748        m_pHoverLeaveTimer->start();
     749}
     750
     751void UIMiniToolBar::sltHandleToolbarResize()
     752{
     753    /* Adjust geometry: */
     754    adjustGeometry();
     755}
     756
     757void UIMiniToolBar::sltAutoHideToggled()
     758{
     759    /* Propagate from child: */
     760    setAutoHide(m_pToolbar->autoHide(), false);
     761    emit sigAutoHideToggled(m_pToolbar->autoHide());
     762}
     763
     764void UIMiniToolBar::sltHoverEnter()
     765{
     766    /* Mark as 'hovered' if necessary: */
     767    if (!m_fHovered)
     768    {
     769        m_fHovered = true;
     770        emit sigHoverEnter();
     771    }
     772}
     773
     774void UIMiniToolBar::sltHoverLeave()
     775{
     776    /* Mark as 'unhovered' if necessary: */
     777    if (m_fHovered)
     778    {
     779        m_fHovered = false;
     780        if (m_fAutoHide)
     781            emit sigHoverLeave();
     782    }
     783}
     784
     785void UIMiniToolBar::sltCheckWindowActivationSanity()
     786{
     787    /* Do nothing if parent window is already active: */
     788    if (   m_pParent
     789        && QGuiApplication::focusWindow() == m_pParent->windowHandle())
     790        return;
     791
     792    /* We can't touch window activation if have modal or popup
     793     * window opened, otherwise internal Qt state get flawed: */
     794    if (   QApplication::activeModalWidget()
     795        || QApplication::activePopupWidget())
     796    {
     797        /* But we should recheck the state in let's say 300ms: */
     798        QTimer::singleShot(300, this, SLOT(sltCheckWindowActivationSanity()));
     799        return;
     800    }
     801
     802    /* Notify listener about we have stole window activation: */
     803    emit sigNotifyAboutWindowActivationStolen();
     804}
     805
     806void UIMiniToolBar::sltHide()
     807{
     808    LogRel(("GUI: Hide mini-toolbar for window #%d\n", m_iWindowIndex));
     809
     810#if defined(VBOX_WS_MAC)
     811
     812    // Nothing
     813
     814#elif defined(VBOX_WS_WIN)
     815
     816    /* Reset window state to NONE and hide it: */
     817    setWindowState(Qt::WindowNoState);
     818    hide();
     819
     820#elif defined(VBOX_WS_X11)
     821
     822    /* Just hide window: */
     823    hide();
     824
     825#else
     826
     827# warning "port me"
     828
     829#endif
     830}
     831
     832void UIMiniToolBar::sltShow()
     833{
     834    LogRel(("GUI: Show mini-toolbar for window #%d\n", m_iWindowIndex));
     835
     836    /* Update transience: */
     837    sltAdjustTransience();
     838
     839#if defined(VBOX_WS_MAC)
     840
     841    // Nothing
     842
     843#elif defined(VBOX_WS_WIN)
     844
     845    // WORKAROUND:
     846    // If the host-screen is changed => we should
     847    // reset window state to NONE first because
     848    // we need an expose on showFullScreen call.
     849    if (m_geometryType == GeometryType_Full)
     850        setWindowState(Qt::WindowNoState);
     851
     852    /* Adjust window: */
     853    sltAdjust();
     854    /* Show window in necessary mode: */
     855    switch (m_geometryType)
     856    {
     857        case GeometryType_Available:
     858        {
     859            /* Show normal: */
     860            show();
     861            break;
     862        }
     863        case GeometryType_Full:
     864        {
     865            /* Show full-screen: */
     866            showFullScreen();
     867            break;
     868        }
     869    }
     870
     871#elif defined(VBOX_WS_X11)
     872
     873    /* Show window in necessary mode: */
     874    switch (m_geometryType)
     875    {
     876        case GeometryType_Available:
     877        {
     878            /* Adjust window: */
     879            sltAdjust();
     880            /* Show maximized: */
     881            if (!isMaximized())
     882                showMaximized();
     883            break;
     884        }
     885        case GeometryType_Full:
     886        {
     887            /* Show full-screen: */
     888            showFullScreen();
     889            /* Adjust window: */
     890            sltAdjust();
     891            break;
     892        }
     893    }
     894
     895#else
     896
     897# warning "port me"
     898
     899#endif
     900
     901    /* Simulate toolbar auto-hiding: */
     902    simulateToolbarAutoHiding();
     903}
     904
     905void UIMiniToolBar::sltAdjust()
     906{
     907    LogRel(("GUI: Adjust mini-toolbar for window #%d\n", m_iWindowIndex));
     908
     909    /* Get corresponding host-screen: */
     910    const int iHostScreenCount = UIDesktopWidgetWatchdog::screenCount();
     911    int iHostScreen = UIDesktopWidgetWatchdog::screenNumber(m_pParent);
     912    // WORKAROUND:
     913    // When switching host-screen count, especially in complex cases where RDP client is "replacing" host-screen(s) with own virtual-screen(s),
     914    // Qt could behave quite arbitrary and laggy, and due to racing there could be a situation when QDesktopWidget::screenNumber() returns -1
     915    // as a host-screen number where the parent window is currently located. We should handle this situation anyway, so let's assume the parent
     916    // window is located on primary (0) host-screen if it's present or ignore this request at all.
     917    if (iHostScreen < 0 || iHostScreen >= iHostScreenCount)
     918    {
     919        if (iHostScreenCount > 0)
     920        {
     921            LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Fallback to primary.\n", m_iWindowIndex, iHostScreen));
     922            iHostScreen = 0;
     923        }
     924        else
     925        {
     926            LogRel(("GUI:  Mini-toolbar parent window #%d is located on invalid host-screen #%d. Ignore request.\n", m_iWindowIndex, iHostScreen));
     927            return;
     928        }
     929    }
     930
     931    /* Get corresponding working area: */
     932    QRect workingArea;
     933    switch (m_geometryType)
     934    {
     935        case GeometryType_Available: workingArea = gpDesktop->availableGeometry(iHostScreen); break;
     936        case GeometryType_Full:      workingArea = gpDesktop->screenGeometry(iHostScreen); break;
     937    }
     938    Q_UNUSED(workingArea);
     939
     940#if defined(VBOX_WS_MAC)
     941
     942    // Nothing
     943
     944#elif defined(VBOX_WS_WIN)
     945
     946    switch (m_geometryType)
     947    {
     948        case GeometryType_Available:
     949        {
     950            /* Set appropriate window size: */
     951            const QSize newSize = workingArea.size();
     952            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
     953                     m_iWindowIndex, newSize.width(), newSize.height()));
     954            resize(newSize);
     955
     956            /* Move window onto required screen: */
     957            const QPoint newPosition = workingArea.topLeft();
     958            LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
     959                     m_iWindowIndex, newPosition.x(), newPosition.y()));
     960            move(newPosition);
     961
     962            break;
     963        }
     964        case GeometryType_Full:
     965        {
     966            /* Map window onto required screen: */
     967            LogRel(("GUI:  Map mini-toolbar for window #%d to screen %d of %d\n",
     968                     m_iWindowIndex, iHostScreen, qApp->screens().size()));
     969            windowHandle()->setScreen(qApp->screens().at(iHostScreen));
     970
     971            /* Set appropriate window size: */
     972            const QSize newSize = workingArea.size();
     973            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
     974                     m_iWindowIndex, newSize.width(), newSize.height()));
     975            resize(newSize);
     976
     977            break;
     978        }
     979    }
     980
     981#elif defined(VBOX_WS_X11)
     982
     983    switch (m_geometryType)
     984    {
     985        case GeometryType_Available:
     986        {
     987            /* Make sure we are located on corresponding host-screen: */
     988            if (   UIDesktopWidgetWatchdog::screenCount() > 1
     989                && (x() != workingArea.x() || y() != workingArea.y()))
     990            {
     991                // WORKAROUND:
     992                // With Qt5 on KDE we can't just move the window onto desired host-screen if
     993                // window is maximized. So we have to show it normal first of all:
     994                if (isVisible() && isMaximized())
     995                    showNormal();
     996
     997                // WORKAROUND:
     998                // With Qt5 on X11 we can't just move the window onto desired host-screen if
     999                // window size is more than the available geometry (working area) of that
     1000                // host-screen. So we are resizing it to a smaller size first of all:
     1001                const QSize newSize = workingArea.size() * .9;
     1002                LogRel(("GUI:  Resize mini-toolbar for window #%d to smaller size %dx%d\n",
     1003                        m_iWindowIndex, newSize.width(), newSize.height()));
     1004                resize(newSize);
     1005
     1006                /* Move window onto required screen: */
     1007                const QPoint newPosition = workingArea.topLeft();
     1008                LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
     1009                        m_iWindowIndex, newPosition.x(), newPosition.y()));
     1010                move(newPosition);
     1011            }
     1012
     1013            break;
     1014        }
     1015        case GeometryType_Full:
     1016        {
     1017            /* Determine whether we should use the native full-screen mode: */
     1018            const bool fUseNativeFullScreen =    NativeWindowSubsystem::X11SupportsFullScreenMonitorsProtocol()
     1019                                              && !gEDataManager->legacyFullscreenModeRequested();
     1020            if (fUseNativeFullScreen)
     1021            {
     1022                /* Tell recent window managers which host-screen this window should be mapped to: */
     1023                NativeWindowSubsystem::X11SetFullScreenMonitor(this, iHostScreen);
     1024            }
     1025
     1026            /* Set appropriate window size: */
     1027            const QSize newSize = workingArea.size();
     1028            LogRel(("GUI:  Resize mini-toolbar for window #%d to %dx%d\n",
     1029                    m_iWindowIndex, newSize.width(), newSize.height()));
     1030            resize(newSize);
     1031
     1032            /* Move window onto required screen: */
     1033            const QPoint newPosition = workingArea.topLeft();
     1034            LogRel(("GUI:  Move mini-toolbar for window #%d to %dx%d\n",
     1035                    m_iWindowIndex, newPosition.x(), newPosition.y()));
     1036            move(newPosition);
     1037
     1038            /* Re-apply the full-screen state lost on above move(): */
     1039            setWindowState(Qt::WindowFullScreen);
     1040
     1041            break;
     1042        }
     1043    }
     1044
     1045#else
     1046
     1047# warning "port me"
     1048
     1049#endif
     1050}
     1051
     1052void UIMiniToolBar::sltAdjustTransience()
     1053{
     1054    // WORKAROUND:
     1055    // Make sure win id is generated,
     1056    // else Qt5 can crash otherwise.
     1057    winId();
     1058    m_pParent->winId();
     1059
     1060    /* Add the transience dependency: */
     1061    windowHandle()->setTransientParent(m_pParent->windowHandle());
     1062}
     1063
     1064void UIMiniToolBar::prepare()
     1065{
     1066    /* Install event-filters: */
     1067    installEventFilter(this);
     1068    m_pParent->installEventFilter(this);
     1069
     1070#if   defined(VBOX_WS_WIN)
     1071    /* No background until first paint-event: */
     1072    setAttribute(Qt::WA_NoSystemBackground);
     1073    /* Enable translucency through Qt API: */
     1074    setAttribute(Qt::WA_TranslucentBackground);
     1075#elif defined(VBOX_WS_X11)
     1076    /* Enable translucency through Qt API if supported: */
     1077    if (uiCommon().isCompositingManagerRunning())
     1078        setAttribute(Qt::WA_TranslucentBackground);
     1079#endif /* VBOX_WS_X11 */
     1080
     1081    /* Make sure we have no focus: */
     1082    setFocusPolicy(Qt::NoFocus);
     1083
     1084    /* Prepare area: */
     1085    m_pArea = new QWidget;
     1086    {
     1087        /* Allow any area size: */
     1088        m_pArea->setMinimumSize(QSize(1, 1));
     1089        /* Configure own background: */
     1090        QPalette pal = m_pArea->palette();
     1091        pal.setColor(QPalette::Window, QColor(Qt::transparent));
     1092        m_pArea->setPalette(pal);
     1093        /* Layout area according parent-widget: */
     1094        QVBoxLayout *pMainLayout = new QVBoxLayout(this);
     1095        pMainLayout->setContentsMargins(0, 0, 0, 0);
     1096        pMainLayout->addWidget(m_pArea);
     1097        /* Make sure we have no focus: */
     1098        m_pArea->setFocusPolicy(Qt::NoFocus);
     1099    }
     1100
     1101    /* Prepare mini-toolbar: */
     1102    m_pToolbar = new UIMiniToolBarPrivate;
     1103    {
     1104        /* Make sure we have no focus: */
     1105        m_pToolbar->setFocusPolicy(Qt::NoFocus);
     1106        /* Propagate known options to child: */
     1107        m_pToolbar->setAutoHide(m_fAutoHide);
     1108        m_pToolbar->setAlignment(m_alignment);
     1109        /* Configure own background: */
     1110        QPalette pal = m_pToolbar->palette();
     1111        pal.setColor(QPalette::Window, QApplication::palette().color(QPalette::Window));
     1112        m_pToolbar->setPalette(pal);
     1113        /* Configure child connections: */
     1114        connect(m_pToolbar, &UIMiniToolBarPrivate::sigResized, this, &UIMiniToolBar::sltHandleToolbarResize);
     1115        connect(m_pToolbar, &UIMiniToolBarPrivate::sigAutoHideToggled, this, &UIMiniToolBar::sltAutoHideToggled);
     1116        connect(m_pToolbar, &UIMiniToolBarPrivate::sigMinimizeAction, this, &UIMiniToolBar::sigMinimizeAction);
     1117        connect(m_pToolbar, &UIMiniToolBarPrivate::sigExitAction, this, &UIMiniToolBar::sigExitAction);
     1118        connect(m_pToolbar, &UIMiniToolBarPrivate::sigCloseAction, this, &UIMiniToolBar::sigCloseAction);
     1119        /* Add child to area: */
     1120        m_pToolbar->setParent(m_pArea);
     1121        /* Make sure we have no focus: */
     1122        m_pToolbar->setFocusPolicy(Qt::NoFocus);
     1123    }
     1124
     1125    /* Prepare hover-enter/leave timers: */
     1126    m_pHoverEnterTimer = new QTimer(this);
     1127    {
     1128        m_pHoverEnterTimer->setSingleShot(true);
     1129        m_pHoverEnterTimer->setInterval(500);
     1130        connect(m_pHoverEnterTimer, &QTimer::timeout, this, &UIMiniToolBar::sltHoverEnter);
     1131    }
     1132    m_pHoverLeaveTimer = new QTimer(this);
     1133    {
     1134        m_pHoverLeaveTimer->setSingleShot(true);
     1135        m_pHoverLeaveTimer->setInterval(500);
     1136        connect(m_pHoverLeaveTimer, &QTimer::timeout, this, &UIMiniToolBar::sltHoverLeave);
     1137    }
     1138
     1139    /* Install 'auto-hide' animation to 'toolbarPosition' property: */
     1140    m_pAnimation = UIAnimation::installPropertyAnimation(this,
     1141                                                         "toolbarPosition",
     1142                                                         "hiddenToolbarPosition", "shownToolbarPosition",
     1143                                                         SIGNAL(sigHoverEnter()), SIGNAL(sigHoverLeave()),
     1144                                                         true);
     1145
     1146    /* Adjust geometry first time: */
     1147    adjustGeometry();
     1148
     1149#ifdef VBOX_WS_X11
     1150    /* Hide mini-toolbar from taskbar and pager: */
     1151    NativeWindowSubsystem::X11SetSkipTaskBarFlag(this);
     1152    NativeWindowSubsystem::X11SetSkipPagerFlag(this);
     1153#endif
     1154}
     1155
     1156void UIMiniToolBar::cleanup()
     1157{
     1158    /* Stop hover-enter/leave timers: */
     1159    if (m_pHoverEnterTimer && m_pHoverEnterTimer->isActive())
     1160        m_pHoverEnterTimer->stop();
     1161    if (m_pHoverLeaveTimer && m_pHoverLeaveTimer->isActive())
     1162        m_pHoverLeaveTimer->stop();
     1163
     1164    /* Destroy animation before toolbar: */
     1165    delete m_pAnimation;
     1166    m_pAnimation = 0;
     1167
     1168    /* Destroy toolbar after animation: */
     1169    delete m_pToolbar;
     1170    m_pToolbar = 0;
     1171}
     1172
    11691173void UIMiniToolBar::simulateToolbarAutoHiding()
    11701174{
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h

    r96407 r97847  
    117117    void adjustGeometry();
    118118
     119protected:
     120
     121    /** Filters @a pEvent if <i>this</i> object has been
     122      * installed as an event-filter for the @a pWatched. */
     123    virtual bool eventFilter(QObject *pWatched, QEvent *pEvent) RT_OVERRIDE;
     124
     125    /** Resize @a pEvent handler. */
     126    virtual void resizeEvent(QResizeEvent *pEvent) RT_OVERRIDE;
     127
     128    /** Mouse enter @a pEvent handler. */
     129#ifdef VBOX_IS_QT6_OR_LATER
     130    virtual void enterEvent(QEnterEvent *pEvent) RT_OVERRIDE;
     131#else
     132    virtual void enterEvent(QEvent *pEvent) RT_OVERRIDE;
     133#endif
     134    /** Mouse leave @a pEvent handler. */
     135    virtual void leaveEvent(QEvent *pEvent) RT_OVERRIDE;
     136
    119137private slots:
    120138
     
    148166    /** Cleanup routine. */
    149167    void cleanup();
    150 
    151     /** Mouse enter @a pEvent handler. */
    152     void enterEvent(QEvent *pEvent);
    153     /** Mouse leave @a pEvent handler. */
    154     void leaveEvent(QEvent *pEvent);
    155 
    156     /** Resize @a pEvent handler. */
    157     void resizeEvent(QResizeEvent *pEvent);
    158 
    159     /** Filters @a pEvent if <i>this</i> object has been
    160       * installed as an event-filter for the @a pWatched. */
    161     bool eventFilter(QObject *pWatched, QEvent *pEvent);
    162168
    163169    /** Simulates auto-hide animation. */
Note: See TracChangeset for help on using the changeset viewer.

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