- Timestamp:
- Dec 20, 2022 2:59:14 PM (2 years ago)
- 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 559 559 setMask(m_pToolbar->geometry()); 560 560 #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_pParent601 && QGuiApplication::focusWindow() == m_pParent->windowHandle())602 return;603 604 /* We can't touch window activation if have modal or popup605 * 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 // Nothing625 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 #else638 639 # warning "port me"640 641 #endif642 }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 // Nothing654 655 #elif defined(VBOX_WS_WIN)656 657 // WORKAROUND:658 // If the host-screen is changed => we should659 // reset window state to NONE first because660 // 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 #else708 709 # warning "port me"710 711 #endif712 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 -1727 // as a host-screen number where the parent window is currently located. We should handle this situation anyway, so let's assume the parent728 // 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 else737 {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 // Nothing755 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() > 1801 && (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 if805 // 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 if811 // window size is more than the available geometry (working area) of that812 // 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 #else858 859 # warning "port me"860 861 #endif862 }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_X11962 /* Hide mini-toolbar from taskbar and pager: */963 NativeWindowSubsystem::X11SetSkipTaskBarFlag(this);964 NativeWindowSubsystem::X11SetSkipPagerFlag(this);965 #endif966 }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 event1000 // when the mouse cursor is on the border of screen1001 // even if underlying widget is on the border of1002 // screen as well, we should detect and ignore that.1003 // Besides that, this is a good way to keep the1004 // tool-bar visible when the mouse moving through1005 // the desktop strut till the real screen border.1006 const QPoint cursorPosition = QCursor::pos();1007 if ( cursorPosition.y() <= y() + 11008 || 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();1024 561 } 1025 562 … … 1167 704 } 1168 705 706 void UIMiniToolBar::resizeEvent(QResizeEvent*) 707 { 708 /* Adjust geometry: */ 709 adjustGeometry(); 710 } 711 712 #ifdef VBOX_IS_QT6_OR_LATER 713 void UIMiniToolBar::enterEvent(QEnterEvent*) 714 #else 715 void 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 727 void 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 751 void UIMiniToolBar::sltHandleToolbarResize() 752 { 753 /* Adjust geometry: */ 754 adjustGeometry(); 755 } 756 757 void UIMiniToolBar::sltAutoHideToggled() 758 { 759 /* Propagate from child: */ 760 setAutoHide(m_pToolbar->autoHide(), false); 761 emit sigAutoHideToggled(m_pToolbar->autoHide()); 762 } 763 764 void UIMiniToolBar::sltHoverEnter() 765 { 766 /* Mark as 'hovered' if necessary: */ 767 if (!m_fHovered) 768 { 769 m_fHovered = true; 770 emit sigHoverEnter(); 771 } 772 } 773 774 void 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 785 void 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 806 void 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 832 void 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 905 void 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 1052 void 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 1064 void 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 1156 void 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 1169 1173 void UIMiniToolBar::simulateToolbarAutoHiding() 1170 1174 { -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h
r96407 r97847 117 117 void adjustGeometry(); 118 118 119 protected: 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 119 137 private slots: 120 138 … … 148 166 /** Cleanup routine. */ 149 167 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 been160 * installed as an event-filter for the @a pWatched. */161 bool eventFilter(QObject *pWatched, QEvent *pEvent);162 168 163 169 /** Simulates auto-hide animation. */
Note:
See TracChangeset
for help on using the changeset viewer.