UIMultiScreenLayout.cpp revision 42c3a43fe0633a05ce009eb9a1e3653ddee65f00
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * VBox frontends: Qt GUI ("VirtualBox"):
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * UIMultiScreenLayout class implementation
967ea84c07a4d8a8d89fb846efc0dd5a523d5a85vboxsync * Copyright (C) 2010-2013 Oracle Corporation
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * available from http://www.virtualbox.org. This file is free software;
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * General Public License (GPL) as published by the Free Software
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8bf8c6b1914c9e7e60b1547888400668f1774497vboxsync/* Qt includes: */
8bf8c6b1914c9e7e60b1547888400668f1774497vboxsync/* GUI includes: */
8bf8c6b1914c9e7e60b1547888400668f1774497vboxsync/* COM includes: */
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsyncUIMultiScreenLayout::UIMultiScreenLayout(UIMachineLogic *pMachineLogic)
967ea84c07a4d8a8d89fb846efc0dd5a523d5a85vboxsync /* Calculate host/guest screen count: */
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Cleanup view-menu: */
967ea84c07a4d8a8d89fb846efc0dd5a523d5a85vboxsyncvoid UIMultiScreenLayout::setViewMenu(QMenu *pViewMenu)
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Assign view-menu: */
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Prepare view-menu: */
e5b078efb3ece1a8718cbab43f4744fd0a6d1ca8vboxsync /* Clear screen-map initially: */
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Make a pool of available host screens: */
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync for (int i = 0; i < m_cHostScreens; ++i)
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Load all combinations stored in the settings file.
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync * We have to make sure they are valid, which means there have to be unique combinations
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync * and all guests screens need there own host screen. */
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync CMachine machine = m_pMachineLogic->session().GetMachine();
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync CDisplay display = m_pMachineLogic->session().GetConsole().GetDisplay();
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync bool fShouldWeAutoMountGuestScreens = VBoxGlobal::shouldWeAutoMountGuestScreens(machine, false);
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Initialize variables: */
249378295da4756ab32709a50a419f902f8e4835vboxsync bool fValid = false;
249378295da4756ab32709a50a419f902f8e4835vboxsync /* If the user ever selected a combination in the view menu, we have the following entry: */
249378295da4756ab32709a50a419f902f8e4835vboxsync QString strTest = machine.GetExtraData(QString("%1%2").arg(GUI_VirtualScreenToHostScreen).arg(iGuestScreen));
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Check is this value can be converted: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Revalidate: */
249378295da4756ab32709a50a419f902f8e4835vboxsync && iHostScreen >= 0 && iHostScreen < m_cHostScreens /* In the host screen bounds? */
249378295da4756ab32709a50a419f902f8e4835vboxsync && m_screenMap.key(iHostScreen, -1) == -1; /* Not taken already? */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Check the position of the guest window in normal mode.
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync * This makes sure that on first use the window opens on the same screen as the normal window was before.
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync * This even works with multi-screen. The user just have to move all the normal windows to the target screens
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync * and they will magically open there in seamless/fullscreen also. */
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync QString strTest1 = machine.GetExtraData(GUI_LastNormalWindowPosition + (iGuestScreen > 0 ? QString::number(iGuestScreen): ""));
de138efba2ebd195de75cc07a0b52a9dbdab9fa5vboxsync QRegExp posParser("(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* If parsing was successfully, convert it to a position: */
de138efba2ebd195de75cc07a0b52a9dbdab9fa5vboxsync QPoint p(posParser.cap(1).toInt(&fOk1), posParser.cap(2).toInt(&fOk2));
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Check to which screen the position belongs: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Revalidate: */
249378295da4756ab32709a50a419f902f8e4835vboxsync && iHostScreen >= 0 && iHostScreen < m_cHostScreens /* In the host screen bounds? */
249378295da4756ab32709a50a419f902f8e4835vboxsync && m_screenMap.key(iHostScreen, -1) == -1; /* Not taken already? */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* If still not valid, pick the next one
249378295da4756ab32709a50a419f902f8e4835vboxsync * if there is still available host screen: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Register host screen for the guest screen: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Remove it from the list of available host screens: */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Do we have opinion about what to do with excessive guest-screen? */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Then we have to disable excessive guest-screen: */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync display.SetVideoModeHint(iGuestScreen, false, false, 0, 0, 0, 0, 0);
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Are we still have available host-screens
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync * and have opinion about what to do with disabled guest-screens? */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync if (!availableScreens.isEmpty() && fShouldWeAutoMountGuestScreens)
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* How many excessive host-screens do we have? */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync int cExcessiveHostScreens = availableScreens.size();
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* How many disabled guest-screens do we have? */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync int cDisabledGuestScreens = m_disabledGuestScreens.size();
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* We have to try to enable disabled guest-screens if any: */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync int cGuestScreensToEnable = qMin(cExcessiveHostScreens, cDisabledGuestScreens);
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync for (int iGuestScreenIndex = 0; iGuestScreenIndex < cGuestScreensToEnable; ++iGuestScreenIndex)
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Get corresponding guest-screen: */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync int iGuestScreen = m_disabledGuestScreens[iGuestScreenIndex];
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Re-enable guest-screen with the old arguments: */
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync display.GetScreenResolution(iGuestScreen, iWidth, iHeight, iBpp);
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync display.SetVideoModeHint(iGuestScreen, true, false, 0, 0, iWidth, iHeight, iBpp);
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Update menu actions: */
e5b078efb3ece1a8718cbab43f4744fd0a6d1ca8vboxsync /* Recalculate host/guest screen count: */
e5b078efb3ece1a8718cbab43f4744fd0a6d1ca8vboxsync /* Update view-menu: */
e5b078efb3ece1a8718cbab43f4744fd0a6d1ca8vboxsync /* Update layout: */
967ea84c07a4d8a8d89fb846efc0dd5a523d5a85vboxsyncint UIMultiScreenLayout::hostScreenForGuestScreen(int iScreenId) const
e5b078efb3ece1a8718cbab43f4744fd0a6d1ca8vboxsyncbool UIMultiScreenLayout::hasHostScreenForGuestScreen(int iScreenId) const
452fe6c0ad673fa5006fe2c24b76a1a54e4ff499vboxsyncquint64 UIMultiScreenLayout::memoryRequirements() const
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsyncbool UIMultiScreenLayout::isHostTaskbarCovert() const
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync /* Check for all screens which are in use if they have some
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync * taskbar/menubar/dock on it. Its done by comparing the available with the
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync * screen geometry. Only if they are the same for all screens, there are no
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync * host area covert. This is a little bit ugly, but there seems no other
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync * way to find out if we are on a screen where the taskbar/dock or whatever
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync * is present. */
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync if (pDW->availableGeometry(hostScreen) != pDW->screenGeometry(hostScreen))
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync return true;
1d0bea51095c7a2f93857174884b4484ea0fcac7vboxsync return false;
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsyncvoid UIMultiScreenLayout::sltScreenLayoutChanged(QAction *pAction)
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Parse incoming information: */
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync /* Search for the virtual screen which is currently displayed on the
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync * requested host screen. When there is one found, we swap both. */
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync int iCurrentGuestScreen = tmpMap.key(iRequestedHostScreen, -1);
249378295da4756ab32709a50a419f902f8e4835vboxsync if (iCurrentGuestScreen != -1 && tmpMap.contains(iRequestedGuestScreen))
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync tmpMap.insert(iCurrentGuestScreen, tmpMap.value(iRequestedGuestScreen));
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync tmpMap.insert(iRequestedGuestScreen, iRequestedHostScreen);
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Check the memory requirements first: */
452fe6c0ad673fa5006fe2c24b76a1a54e4ff499vboxsync bool fSuccess = true;
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync CMachine machine = m_pMachineLogic->session().GetMachine();
452fe6c0ad673fa5006fe2c24b76a1a54e4ff499vboxsync if (m_pMachineLogic->uisession()->isGuestAdditionsActive())
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync quint64 availBits = machine.GetVRAMSize() * _1M * 8;
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* We have too little video memory for the new layout, so say it to the user and revert all the changes: */
452fe6c0ad673fa5006fe2c24b76a1a54e4ff499vboxsync if (m_pMachineLogic->visualStateType() == UIVisualStateType_Seamless)
cb48b678483eed76053da41c3f0f2600eeeed5f4vboxsync msgCenter().cannotSwitchScreenInSeamless((((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M);
78100a023b3725c3611e76d104f41f2c2ccfa440vboxsync fSuccess = msgCenter().cannotSwitchScreenInFullscreen((((usedBits + 7) / 8 + _1M - 1) / _1M) * _1M);
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Make sure memory requirements matched: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Swap the maps: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Update menu actions: */
249378295da4756ab32709a50a419f902f8e4835vboxsync /* Inform the observer: */
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsyncvoid UIMultiScreenLayout::calculateHostMonitorCount()
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsync m_cHostScreens = QApplication::desktop()->screenCount();
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsync#else /* (QT_VERSION >= 0x040600) */
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsync m_cHostScreens = QApplication::desktop()->numScreens();
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsync#endif /* !(QT_VERSION >= 0x040600) */
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsyncvoid UIMultiScreenLayout::calculateGuestScreenCount()
24b149e148cc3fa554adb3225a34b96292d18e9evboxsync /* Get machine: */
ed6ec60d8984cdb1068af0cc3c8b54ef7701b269vboxsync CMachine machine = m_pMachineLogic->session().GetMachine();
42c3a43fe0633a05ce009eb9a1e3653ddee65f00vboxsync /* Enumerate all the guest screens: */
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync for (uint iGuestScreen = 0; iGuestScreen < machine.GetMonitorCount(); ++iGuestScreen)
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync if (m_pMachineLogic->uisession()->isScreenVisible(iGuestScreen))
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Make sure view-menu was set: */
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Cleanup menu first: */
7b601f6c4b83b7e3a0f58a62b198352048c6f7c3vboxsync /* If we do have more than one host/guest screen: */
7b601f6c4b83b7e3a0f58a62b198352048c6f7c3vboxsync if (m_cHostScreens > 1 || m_guestScreens.size() > 1)
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync m_screenMenuList << m_pViewMenu->addMenu(tr("Virtual Screen %1").arg(iGuestScreen + 1));
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync m_screenMenuList.last()->menuAction()->setData(true);
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync QActionGroup *pScreenGroup = new QActionGroup(m_screenMenuList.last());
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync connect(pScreenGroup, SIGNAL(triggered(QAction*)), this, SLOT(sltScreenLayoutChanged(QAction*)));
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync for (int a = 0; a < m_cHostScreens; ++a)
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync QAction *pAction = pScreenGroup->addAction(tr("Use Host Screen %1").arg(a + 1));
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync m_screenMenuList.last()->addActions(pScreenGroup->actions());
7b601f6c4b83b7e3a0f58a62b198352048c6f7c3vboxsync /* Update menu actions: */
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Make sure view-menu was set: */
64d1b5482e82d2306b6a5edc905f8f7085dd30c4vboxsync /* Cleanup view-menu actions: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsyncvoid UIMultiScreenLayout::updateMenuActions(bool fWithSave)
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Get the list of all view-menu actions: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync QList<QAction*> viewMenuActions = gActionPool->action(UIActionIndexRuntime_Menu_View)->menu()->actions();
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Get the list of all view related actions: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Update view actions: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync CMachine machine = m_pMachineLogic->session().GetMachine();
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync for (int iViewAction = 0; iViewAction < viewActions.size(); ++iViewAction)
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync int iHostScreen = m_screenMap.value(iGuestScreen, -1);
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync QString strHostScreen(iHostScreen != -1 ? QString::number(iHostScreen) : QString());
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync machine.SetExtraData(QString("%1%2").arg(GUI_VirtualScreenToHostScreen).arg(iViewAction), strHostScreen);
0555766825ef1f1699618d57768bfe7bdea0ae0fvboxsync QList<QAction*> screenActions = viewActions.at(iViewAction)->menu()->actions();
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync /* Update screen actions: */
05a789df00b1b166fe2a6ede4562331679ca0c4cvboxsync pTmpAction->setChecked(RT_HIWORD(pTmpAction->data().toInt()) == iHostScreen);
6a7e2ecbbcc452e120a12c6996aee7397c57a9d7vboxsyncquint64 UIMultiScreenLayout::memoryRequirements(const QMap<int, int> &screenLayout) const
7ac6803839f30a88cff7d938c64c5c75c220b4favboxsync CDisplay display = m_pMachineLogic->uisession()->session().GetConsole().GetDisplay();
7abe5cfaba8f21303dcefca4fcd1c6c0a192eaf3vboxsync if (m_pMachineLogic->visualStateType() == UIVisualStateType_Seamless)
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync screen = QApplication::desktop()->availableGeometry(screenLayout.value(iGuestScreen, 0));
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync screen = QApplication::desktop()->screenGeometry(screenLayout.value(iGuestScreen, 0));
b7cd916020f507a173c9cdd6c56c4a9a4574640dvboxsync display.GetScreenResolution(iGuestScreen, width, height, guestBpp);
452fe6c0ad673fa5006fe2c24b76a1a54e4ff499vboxsync _1M * 8; /* current cache per screen - may be changed in future */