Changeset 91066 in vbox for trunk/src/VBox
- Timestamp:
- Sep 1, 2021 3:56:33 PM (3 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.cpp
r91057 r91066 43 43 #endif 44 44 #ifdef VBOX_WS_X11 45 # include <QScreen>46 # include <QScrollBar>47 # include <QTextBrowser>48 45 # include <QX11Info> 49 46 #endif … … 127 124 #include <iprt/stream.h> 128 125 #include <iprt/system.h> 129 #ifdef VBOX_WS_X11130 # include <iprt/mem.h>131 #endif132 126 #include <VBox/sup.h> 133 127 #include <VBox/VBoxOGL.h> … … 142 136 # include <iprt/win/shlobj.h> 143 137 #endif 144 #ifdef VBOX_WS_X11145 # include <xcb/xcb.h>146 #endif147 138 148 139 /* External includes: */ … … 150 141 #ifdef VBOX_WS_MAC 151 142 # include <sys/utsname.h> 152 #endif153 #ifdef VBOX_WS_X11154 // WORKAROUND:155 // typedef CARD8 BOOL in Xmd.h conflicts with #define BOOL PRBool156 // in COMDefs.h. A better fix would be to isolate X11-specific157 // stuff by placing XX* helpers below to a separate source file.158 # undef BOOL159 # include <X11/X.h>160 # include <X11/Xmd.h>161 # include <X11/Xlib.h>162 # include <X11/Xatom.h>163 # include <X11/Xutil.h>164 # include <X11/extensions/Xinerama.h>165 # define BOOL PRBool166 143 #endif 167 144 … … 1518 1495 } 1519 1496 1520 #ifdef VBOX_WS_X111521 typedef struct {1522 /** User specified flags */1523 uint32_t flags;1524 /** User-specified position */1525 int32_t x, y;1526 /** User-specified size */1527 int32_t width, height;1528 /** Program-specified minimum size */1529 int32_t min_width, min_height;1530 /** Program-specified maximum size */1531 int32_t max_width, max_height;1532 /** Program-specified resize increments */1533 int32_t width_inc, height_inc;1534 /** Program-specified minimum aspect ratios */1535 int32_t min_aspect_num, min_aspect_den;1536 /** Program-specified maximum aspect ratios */1537 int32_t max_aspect_num, max_aspect_den;1538 /** Program-specified base size */1539 int32_t base_width, base_height;1540 /** Program-specified window gravity */1541 uint32_t win_gravity;1542 } xcb_size_hints_t;1543 #endif /* VBOX_WS_X11 */1544 1545 1497 /* static */ 1546 1498 void UICommon::setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h) … … 1609 1561 } 1610 1562 1611 #if defined(VBOX_WS_X11)1612 1613 static char *XXGetProperty(Display *pDpy, Window windowHandle, Atom propType, const char *pszPropName)1614 {1615 Atom propNameAtom = XInternAtom(pDpy, pszPropName, True /* only_if_exists */);1616 if (propNameAtom == None)1617 return NULL;1618 1619 Atom actTypeAtom = None;1620 int actFmt = 0;1621 unsigned long nItems = 0;1622 unsigned long nBytesAfter = 0;1623 unsigned char *propVal = NULL;1624 int rc = XGetWindowProperty(pDpy, windowHandle, propNameAtom,1625 0, LONG_MAX, False /* delete */,1626 propType, &actTypeAtom, &actFmt,1627 &nItems, &nBytesAfter, &propVal);1628 if (rc != Success)1629 return NULL;1630 1631 return reinterpret_cast<char*>(propVal);1632 }1633 1634 static Bool XXSendClientMessage(Display *pDpy, Window windowHandle, const char *pszMsg,1635 unsigned long aData0 = 0, unsigned long aData1 = 0,1636 unsigned long aData2 = 0, unsigned long aData3 = 0,1637 unsigned long aData4 = 0)1638 {1639 Atom msgAtom = XInternAtom(pDpy, pszMsg, True /* only_if_exists */);1640 if (msgAtom == None)1641 return False;1642 1643 XEvent ev;1644 1645 ev.xclient.type = ClientMessage;1646 ev.xclient.serial = 0;1647 ev.xclient.send_event = True;1648 ev.xclient.display = pDpy;1649 ev.xclient.window = windowHandle;1650 ev.xclient.message_type = msgAtom;1651 1652 /* Always send as 32 bit for now: */1653 ev.xclient.format = 32;1654 ev.xclient.data.l[0] = aData0;1655 ev.xclient.data.l[1] = aData1;1656 ev.xclient.data.l[2] = aData2;1657 ev.xclient.data.l[3] = aData3;1658 ev.xclient.data.l[4] = aData4;1659 1660 return XSendEvent(pDpy, DefaultRootWindow(pDpy), False,1661 SubstructureRedirectMask, &ev) != 0;1662 }1663 1664 #endif1665 1666 1563 /* static */ 1667 1564 bool UICommon::activateWindow(WId wId, bool fSwitchDesktop /* = true */) … … 1683 1580 #elif defined(VBOX_WS_X11) 1684 1581 1685 Display *pDisplay = QX11Info::display(); 1686 1687 if (fSwitchDesktop) 1688 { 1689 /* try to find the desktop ID using the NetWM property */ 1690 CARD32 *pDesktop = (CARD32 *) XXGetProperty(pDisplay, wId, XA_CARDINAL, 1691 "_NET_WM_DESKTOP"); 1692 if (pDesktop == NULL) 1693 // WORKAROUND: 1694 // if the NetWM properly is not supported try to find 1695 // the desktop ID using the GNOME WM property. 1696 pDesktop = (CARD32 *) XXGetProperty(pDisplay, wId, XA_CARDINAL, 1697 "_WIN_WORKSPACE"); 1698 1699 if (pDesktop != NULL) 1700 { 1701 Bool ok = XXSendClientMessage(pDisplay, DefaultRootWindow(pDisplay), 1702 "_NET_CURRENT_DESKTOP", 1703 *pDesktop); 1704 if (!ok) 1705 { 1706 Log1WarningFunc(("Couldn't switch to pDesktop=%08X\n", pDesktop)); 1707 fResult = false; 1708 } 1709 XFree(pDesktop); 1710 } 1711 else 1712 { 1713 Log1WarningFunc(("Couldn't find a pDesktop ID for wId=%08X\n", wId)); 1714 fResult = false; 1715 } 1716 } 1717 1718 Bool ok = XXSendClientMessage(pDisplay, wId, "_NET_ACTIVE_WINDOW"); 1719 fResult &= !!ok; 1720 1721 XRaiseWindow(pDisplay, wId); 1582 return NativeWindowSubsystem::X11ActivateWindow(wId, fSwitchDesktop); 1722 1583 1723 1584 #else … … 1735 1596 return fResult; 1736 1597 } 1737 1738 #if defined(VBOX_WS_X11)1739 1740 /* static */1741 bool UICommon::supportsFullScreenMonitorsProtocolX11()1742 {1743 /* This method tests whether the current X11 window manager supports full-screen mode as we need it.1744 * Unfortunately the EWMH specification was not fully clear about whether we can expect to find1745 * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all1746 * interesting window managers. If this fails for a user when you think it should succeed1747 * they should try executing:1748 * xprop -root | egrep -w '_NET_WM_FULLSCREEN_MONITORS|_NET_WM_STATE|_NET_WM_STATE_FULLSCREEN'1749 * in an X11 terminal window.1750 * All three strings should be found under a property called "_NET_SUPPORTED(ATOM)". */1751 1752 /* Using a global to get at the display does not feel right, but that is how it is done elsewhere in the code. */1753 Display *pDisplay = QX11Info::display();1754 Atom atomSupported = XInternAtom(pDisplay, "_NET_SUPPORTED",1755 True /* only_if_exists */);1756 Atom atomWMFullScreenMonitors = XInternAtom(pDisplay,1757 "_NET_WM_FULLSCREEN_MONITORS",1758 True /* only_if_exists */);1759 Atom atomWMState = XInternAtom(pDisplay,1760 "_NET_WM_STATE",1761 True /* only_if_exists */);1762 Atom atomWMStateFullScreen = XInternAtom(pDisplay,1763 "_NET_WM_STATE_FULLSCREEN",1764 True /* only_if_exists */);1765 bool fFoundFullScreenMonitors = false;1766 bool fFoundState = false;1767 bool fFoundStateFullScreen = false;1768 Atom atomType;1769 int cFormat;1770 unsigned long cItems;1771 unsigned long cbLeft;1772 Atom *pAtomHints;1773 int rc;1774 unsigned i;1775 1776 if ( atomSupported == None || atomWMFullScreenMonitors == None1777 || atomWMState == None || atomWMStateFullScreen == None)1778 return false;1779 /* Get atom value: */1780 rc = XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay),1781 atomSupported, 0, 0x7fffffff /*LONG_MAX*/,1782 False /* delete */, XA_ATOM, &atomType,1783 &cFormat, &cItems, &cbLeft,1784 (unsigned char **)&pAtomHints);1785 if (rc != Success)1786 return false;1787 if (pAtomHints == NULL)1788 return false;1789 if (atomType == XA_ATOM && cFormat == 32 && cbLeft == 0)1790 for (i = 0; i < cItems; ++i)1791 {1792 if (pAtomHints[i] == atomWMFullScreenMonitors)1793 fFoundFullScreenMonitors = true;1794 if (pAtomHints[i] == atomWMState)1795 fFoundState = true;1796 if (pAtomHints[i] == atomWMStateFullScreen)1797 fFoundStateFullScreen = true;1798 }1799 XFree(pAtomHints);1800 return fFoundFullScreenMonitors && fFoundState && fFoundStateFullScreen;1801 }1802 1803 /* static */1804 bool UICommon::setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId)1805 {1806 return XXSendClientMessage(QX11Info::display(),1807 pWidget->window()->winId(),1808 "_NET_WM_FULLSCREEN_MONITORS",1809 uScreenId, uScreenId, uScreenId, uScreenId,1810 1 /* Source indication (1 = normal application) */);1811 }1812 1813 /* static */1814 QVector<Atom> UICommon::flagsNetWmState(QWidget *pWidget)1815 {1816 /* Get display: */1817 Display *pDisplay = QX11Info::display();1818 1819 /* Prepare atoms: */1820 QVector<Atom> resultNetWmState;1821 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1822 1823 /* Get the size of the property data: */1824 Atom actual_type;1825 int iActualFormat;1826 ulong uPropertyLength;1827 ulong uBytesLeft;1828 uchar *pPropertyData = 0;1829 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),1830 net_wm_state, 0, 0, False, XA_ATOM, &actual_type, &iActualFormat,1831 &uPropertyLength, &uBytesLeft, &pPropertyData) == Success &&1832 actual_type == XA_ATOM && iActualFormat == 32)1833 {1834 resultNetWmState.resize(uBytesLeft / 4);1835 XFree((char*)pPropertyData);1836 pPropertyData = 0;1837 1838 /* Fetch all data: */1839 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),1840 net_wm_state, 0, resultNetWmState.size(), False, XA_ATOM, &actual_type, &iActualFormat,1841 &uPropertyLength, &uBytesLeft, &pPropertyData) != Success)1842 resultNetWmState.clear();1843 else if (uPropertyLength != (ulong)resultNetWmState.size())1844 resultNetWmState.resize(uPropertyLength);1845 1846 /* Put it into resultNetWmState: */1847 if (!resultNetWmState.isEmpty())1848 memcpy(resultNetWmState.data(), pPropertyData, resultNetWmState.size() * sizeof(Atom));1849 if (pPropertyData)1850 XFree((char*)pPropertyData);1851 }1852 1853 /* Return result: */1854 return resultNetWmState;1855 }1856 1857 /* static */1858 bool UICommon::isFullScreenFlagSet(QWidget *pWidget)1859 {1860 /* Get display: */1861 Display *pDisplay = QX11Info::display();1862 1863 /* Prepare atoms: */1864 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);1865 1866 /* Check if flagsNetWmState(pWidget) contains full-screen flag: */1867 return flagsNetWmState(pWidget).contains(net_wm_state_fullscreen);1868 }1869 1870 /* static */1871 void UICommon::setFullScreenFlag(QWidget *pWidget)1872 {1873 /* Get display: */1874 Display *pDisplay = QX11Info::display();1875 1876 /* Prepare atoms: */1877 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);1878 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1879 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);1880 1881 /* Append resultNetWmState with fullscreen flag if necessary: */1882 if (!resultNetWmState.contains(net_wm_state_fullscreen))1883 {1884 resultNetWmState.append(net_wm_state_fullscreen);1885 /* Apply property to widget again: */1886 XChangeProperty(pDisplay, pWidget->window()->winId(),1887 net_wm_state, XA_ATOM, 32, PropModeReplace,1888 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());1889 }1890 }1891 1892 /* static */1893 void UICommon::setSkipTaskBarFlag(QWidget *pWidget)1894 {1895 /* Get display: */1896 Display *pDisplay = QX11Info::display();1897 1898 /* Prepare atoms: */1899 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);1900 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1901 Atom net_wm_state_skip_taskbar = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", True /* only if exists */);1902 1903 /* Append resultNetWmState with skip-taskbar flag if necessary: */1904 if (!resultNetWmState.contains(net_wm_state_skip_taskbar))1905 {1906 resultNetWmState.append(net_wm_state_skip_taskbar);1907 /* Apply property to widget again: */1908 XChangeProperty(pDisplay, pWidget->window()->winId(),1909 net_wm_state, XA_ATOM, 32, PropModeReplace,1910 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());1911 }1912 }1913 1914 /* static */1915 void UICommon::setSkipPagerFlag(QWidget *pWidget)1916 {1917 /* Get display: */1918 Display *pDisplay = QX11Info::display();1919 1920 /* Prepare atoms: */1921 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);1922 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1923 Atom net_wm_state_skip_pager = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_PAGER", True /* only if exists */);1924 1925 /* Append resultNetWmState with skip-pager flag if necessary: */1926 if (!resultNetWmState.contains(net_wm_state_skip_pager))1927 {1928 resultNetWmState.append(net_wm_state_skip_pager);1929 /* Apply property to widget again: */1930 XChangeProperty(pDisplay, pWidget->window()->winId(),1931 net_wm_state, XA_ATOM, 32, PropModeReplace,1932 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());1933 }1934 }1935 1936 /* static */1937 void UICommon::setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString)1938 {1939 /* Make sure all arguments set: */1940 AssertReturnVoid(pWidget && !strNameString.isNull() && !strClassString.isNull());1941 1942 /* Define QByteArray objects to make sure data is alive within the scope: */1943 QByteArray nameByteArray;1944 /* Check the existence of RESOURCE_NAME env. variable and override name string if necessary: */1945 const char resourceName[] = "RESOURCE_NAME";1946 if (qEnvironmentVariableIsSet(resourceName))1947 nameByteArray = qgetenv(resourceName);1948 else1949 nameByteArray = strNameString.toLatin1();1950 QByteArray classByteArray = strClassString.toLatin1();1951 1952 AssertReturnVoid(nameByteArray.data() && classByteArray.data());1953 1954 XClassHint windowClass;1955 windowClass.res_name = nameByteArray.data();1956 windowClass.res_class = classByteArray.data();1957 /* Set WM_CLASS of the window to passed name and class strings: */1958 XSetClassHint(QX11Info::display(), pWidget->window()->winId(), &windowClass);1959 }1960 1961 /* static */1962 void UICommon::setXwaylandMayGrabKeyboardFlag(QWidget *pWidget)1963 {1964 XXSendClientMessage(QX11Info::display(), pWidget->window()->winId(),1965 "_XWAYLAND_MAY_GRAB_KEYBOARD", 1);1966 }1967 #endif /* VBOX_WS_X11 */1968 1598 1969 1599 /* static */ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.h
r91057 r91066 45 45 /* Other VBox includes: */ 46 46 #include "VBox/com/Guid.h" 47 48 /* Other includes: */49 #ifdef VBOX_WS_X1150 # include <X11/Xdefs.h>51 #endif52 47 53 48 /* Forward declarations: */ … … 218 213 219 214 #ifdef VBOX_WS_X11 215 /** X11: Returns the type of the Window Manager we are running under. */ 216 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; } 220 217 /** X11: Returns whether the Window Manager we are running under is composition one. */ 221 218 bool isCompositingManagerRunning() const { return m_fCompositingManagerRunning; } 222 /** X11: Returns the type of the Window Manager we are running under. */223 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; }224 219 #endif 225 220 /** @} */ … … 342 337 /** Activates the specified window with given @a wId. Can @a fSwitchDesktop if requested. */ 343 338 static bool activateWindow(WId wId, bool fSwitchDesktop = true); 344 345 #ifdef VBOX_WS_X11346 /** X11: Test whether the current window manager supports full screen mode. */347 static bool supportsFullScreenMonitorsProtocolX11();348 /** X11: Performs mapping of the passed @a pWidget to host-screen with passed @a uScreenId. */349 static bool setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId);350 351 /** X11: Returns a list of current _NET_WM_STATE flags for passed @a pWidget. */352 static QVector<Atom> flagsNetWmState(QWidget *pWidget);353 /** X11: Check whether _NET_WM_STATE_FULLSCREEN flag is set for passed @a pWidget. */354 static bool isFullScreenFlagSet(QWidget *pWidget);355 /** X11: Sets _NET_WM_STATE_FULLSCREEN flag for passed @a pWidget. */356 static void setFullScreenFlag(QWidget *pWidget);357 /** X11: Sets _NET_WM_STATE_SKIP_TASKBAR flag for passed @a pWidget. */358 static void setSkipTaskBarFlag(QWidget *pWidget);359 /** X11: Sets _NET_WM_STATE_SKIP_PAGER flag for passed @a pWidget. */360 static void setSkipPagerFlag(QWidget *pWidget);361 362 /** Assigns WM_CLASS property for passed @a pWidget. */363 static void setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString);364 /** Tell the WM we are well behaved wrt Xwayland keyboard-grabs. This will365 * make the WM turn our grab into a Wayland shortcut inhibition request,366 * so that e.g. alt+tab will get send to the VM instead of moving the367 * focus away from the VM. */368 static void setXwaylandMayGrabKeyboardFlag(QWidget *pWidget);369 #endif /* VBOX_WS_X11 */370 339 371 340 /** Assigns minimum @a pSpinBox to correspond to @a cCount digits. */ -
trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManager.cpp
r91009 r91066 1983 1983 #ifdef VBOX_WS_X11 1984 1984 /* Assign same name to both WM_CLASS name & class for now: */ 1985 UICommon::setWMClass(this, "VirtualBox Manager", "VirtualBox Manager");1985 NativeWindowSubsystem::X11SetWMClass(this, "VirtualBox Manager", "VirtualBox Manager"); 1986 1986 #endif 1987 1987 -
trunk/src/VBox/Frontends/VirtualBox/src/platform/x11/VBoxUtils-x11.cpp
r91065 r91066 24 24 #include <QtXml/QDomElement> 25 25 #include <QX11Info> 26 #include <QWidget> 26 27 27 28 /* GUI includes: */ … … 29 30 30 31 /* Other VBox includes: */ 32 #include <iprt/assert.h> 31 33 #include <VBox/log.h> 32 34 … … 336 338 } 337 339 } 340 341 char *XXGetProperty(Display *pDpy, Window windowHandle, Atom propType, const char *pszPropName) 342 { 343 Atom propNameAtom = XInternAtom(pDpy, pszPropName, True /* only_if_exists */); 344 if (propNameAtom == None) 345 return NULL; 346 347 Atom actTypeAtom = None; 348 int actFmt = 0; 349 unsigned long nItems = 0; 350 unsigned long nBytesAfter = 0; 351 unsigned char *propVal = NULL; 352 int rc = XGetWindowProperty(pDpy, windowHandle, propNameAtom, 353 0, LONG_MAX, False /* delete */, 354 propType, &actTypeAtom, &actFmt, 355 &nItems, &nBytesAfter, &propVal); 356 if (rc != Success) 357 return NULL; 358 359 return reinterpret_cast<char*>(propVal); 360 } 361 362 bool XXSendClientMessage(Display *pDpy, Window windowHandle, const char *pszMsg, 363 unsigned long aData0 = 0, unsigned long aData1 = 0, 364 unsigned long aData2 = 0, unsigned long aData3 = 0, 365 unsigned long aData4 = 0) 366 { 367 Atom msgAtom = XInternAtom(pDpy, pszMsg, True /* only_if_exists */); 368 if (msgAtom == None) 369 return false; 370 371 XEvent ev; 372 373 ev.xclient.type = ClientMessage; 374 ev.xclient.serial = 0; 375 ev.xclient.send_event = True; 376 ev.xclient.display = pDpy; 377 ev.xclient.window = windowHandle; 378 ev.xclient.message_type = msgAtom; 379 380 /* Always send as 32 bit for now: */ 381 ev.xclient.format = 32; 382 ev.xclient.data.l[0] = aData0; 383 ev.xclient.data.l[1] = aData1; 384 ev.xclient.data.l[2] = aData2; 385 ev.xclient.data.l[3] = aData3; 386 ev.xclient.data.l[4] = aData4; 387 388 return XSendEvent(pDpy, DefaultRootWindow(pDpy), False, 389 SubstructureRedirectMask, &ev) != 0; 390 } 391 392 bool NativeWindowSubsystem::X11ActivateWindow(WId wId, bool fSwitchDesktop) 393 { 394 bool fResult = false; 395 Display *pDisplay = QX11Info::display(); 396 397 if (fSwitchDesktop) 398 { 399 /* Try to find the desktop ID using the NetWM property: */ 400 CARD32 *pDesktop = (CARD32*)XXGetProperty(pDisplay, wId, XA_CARDINAL, "_NET_WM_DESKTOP"); 401 if (pDesktop == NULL) 402 // WORKAROUND: 403 // if the NetWM properly is not supported try to find 404 // the desktop ID using the GNOME WM property. 405 pDesktop = (CARD32*)XXGetProperty(pDisplay, wId, XA_CARDINAL, "_WIN_WORKSPACE"); 406 407 if (pDesktop != NULL) 408 { 409 bool ok = XXSendClientMessage(pDisplay, DefaultRootWindow(pDisplay), "_NET_CURRENT_DESKTOP", *pDesktop); 410 if (!ok) 411 { 412 Log1WarningFunc(("Couldn't switch to pDesktop=%08X\n", pDesktop)); 413 fResult = false; 414 } 415 XFree(pDesktop); 416 } 417 else 418 { 419 Log1WarningFunc(("Couldn't find a pDesktop ID for wId=%08X\n", wId)); 420 fResult = false; 421 } 422 } 423 424 bool ok = XXSendClientMessage(pDisplay, wId, "_NET_ACTIVE_WINDOW"); 425 fResult &= !!ok; 426 427 XRaiseWindow(pDisplay, wId); 428 return fResult; 429 } 430 431 bool NativeWindowSubsystem::X11SupportsFullScreenMonitorsProtocol() 432 { 433 /* This method tests whether the current X11 window manager supports full-screen mode as we need it. 434 * Unfortunately the EWMH specification was not fully clear about whether we can expect to find 435 * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all 436 * interesting window managers. If this fails for a user when you think it should succeed 437 * they should try executing: 438 * xprop -root | egrep -w '_NET_WM_FULLSCREEN_MONITORS|_NET_WM_STATE|_NET_WM_STATE_FULLSCREEN' 439 * in an X11 terminal window. 440 * All three strings should be found under a property called "_NET_SUPPORTED(ATOM)". */ 441 442 /* Using a global to get at the display does not feel right, but that is how it is done elsewhere in the code. */ 443 Display *pDisplay = QX11Info::display(); 444 Atom atomSupported = XInternAtom(pDisplay, "_NET_SUPPORTED", 445 True /* only_if_exists */); 446 Atom atomWMFullScreenMonitors = XInternAtom(pDisplay, 447 "_NET_WM_FULLSCREEN_MONITORS", 448 True /* only_if_exists */); 449 Atom atomWMState = XInternAtom(pDisplay, 450 "_NET_WM_STATE", 451 True /* only_if_exists */); 452 Atom atomWMStateFullScreen = XInternAtom(pDisplay, 453 "_NET_WM_STATE_FULLSCREEN", 454 True /* only_if_exists */); 455 bool fFoundFullScreenMonitors = false; 456 bool fFoundState = false; 457 bool fFoundStateFullScreen = false; 458 Atom atomType; 459 int cFormat; 460 unsigned long cItems; 461 unsigned long cbLeft; 462 Atom *pAtomHints; 463 int rc; 464 unsigned i; 465 466 if ( atomSupported == None || atomWMFullScreenMonitors == None 467 || atomWMState == None || atomWMStateFullScreen == None) 468 return false; 469 /* Get atom value: */ 470 rc = XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay), 471 atomSupported, 0, 0x7fffffff /*LONG_MAX*/, 472 False /* delete */, XA_ATOM, &atomType, 473 &cFormat, &cItems, &cbLeft, 474 (unsigned char **)&pAtomHints); 475 if (rc != Success) 476 return false; 477 if (pAtomHints == NULL) 478 return false; 479 if (atomType == XA_ATOM && cFormat == 32 && cbLeft == 0) 480 for (i = 0; i < cItems; ++i) 481 { 482 if (pAtomHints[i] == atomWMFullScreenMonitors) 483 fFoundFullScreenMonitors = true; 484 if (pAtomHints[i] == atomWMState) 485 fFoundState = true; 486 if (pAtomHints[i] == atomWMStateFullScreen) 487 fFoundStateFullScreen = true; 488 } 489 XFree(pAtomHints); 490 return fFoundFullScreenMonitors && fFoundState && fFoundStateFullScreen; 491 } 492 493 bool NativeWindowSubsystem::X11SetFullScreenMonitor(QWidget *pWidget, ulong uScreenId) 494 { 495 return XXSendClientMessage(QX11Info::display(), 496 pWidget->window()->winId(), 497 "_NET_WM_FULLSCREEN_MONITORS", 498 uScreenId, uScreenId, uScreenId, uScreenId, 499 1 /* Source indication (1 = normal application) */); 500 } 501 502 QVector<Atom> flagsNetWmState(QWidget *pWidget) 503 { 504 /* Get display: */ 505 Display *pDisplay = QX11Info::display(); 506 507 /* Prepare atoms: */ 508 QVector<Atom> resultNetWmState; 509 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 510 511 /* Get the size of the property data: */ 512 Atom actual_type; 513 int iActualFormat; 514 ulong uPropertyLength; 515 ulong uBytesLeft; 516 uchar *pPropertyData = 0; 517 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(), 518 net_wm_state, 0, 0, False, XA_ATOM, &actual_type, &iActualFormat, 519 &uPropertyLength, &uBytesLeft, &pPropertyData) == Success && 520 actual_type == XA_ATOM && iActualFormat == 32) 521 { 522 resultNetWmState.resize(uBytesLeft / 4); 523 XFree((char*)pPropertyData); 524 pPropertyData = 0; 525 526 /* Fetch all data: */ 527 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(), 528 net_wm_state, 0, resultNetWmState.size(), False, XA_ATOM, &actual_type, &iActualFormat, 529 &uPropertyLength, &uBytesLeft, &pPropertyData) != Success) 530 resultNetWmState.clear(); 531 else if (uPropertyLength != (ulong)resultNetWmState.size()) 532 resultNetWmState.resize(uPropertyLength); 533 534 /* Put it into resultNetWmState: */ 535 if (!resultNetWmState.isEmpty()) 536 memcpy(resultNetWmState.data(), pPropertyData, resultNetWmState.size() * sizeof(Atom)); 537 if (pPropertyData) 538 XFree((char*)pPropertyData); 539 } 540 541 /* Return result: */ 542 return resultNetWmState; 543 } 544 545 #if 0 // unused for now? 546 bool NativeWindowSubsystem::isFullScreenFlagSet(QWidget *pWidget) 547 { 548 /* Get display: */ 549 Display *pDisplay = QX11Info::display(); 550 551 /* Prepare atoms: */ 552 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */); 553 554 /* Check if flagsNetWmState(pWidget) contains full-screen flag: */ 555 return flagsNetWmState(pWidget).contains(net_wm_state_fullscreen); 556 } 557 558 void NativeWindowSubsystem::setFullScreenFlag(QWidget *pWidget) 559 { 560 /* Get display: */ 561 Display *pDisplay = QX11Info::display(); 562 563 /* Prepare atoms: */ 564 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 565 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 566 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */); 567 568 /* Append resultNetWmState with fullscreen flag if necessary: */ 569 if (!resultNetWmState.contains(net_wm_state_fullscreen)) 570 { 571 resultNetWmState.append(net_wm_state_fullscreen); 572 /* Apply property to widget again: */ 573 XChangeProperty(pDisplay, pWidget->window()->winId(), 574 net_wm_state, XA_ATOM, 32, PropModeReplace, 575 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 576 } 577 } 578 #endif // unused for now? 579 580 void NativeWindowSubsystem::X11SetSkipTaskBarFlag(QWidget *pWidget) 581 { 582 /* Get display: */ 583 Display *pDisplay = QX11Info::display(); 584 585 /* Prepare atoms: */ 586 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 587 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 588 Atom net_wm_state_skip_taskbar = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", True /* only if exists */); 589 590 /* Append resultNetWmState with skip-taskbar flag if necessary: */ 591 if (!resultNetWmState.contains(net_wm_state_skip_taskbar)) 592 { 593 resultNetWmState.append(net_wm_state_skip_taskbar); 594 /* Apply property to widget again: */ 595 XChangeProperty(pDisplay, pWidget->window()->winId(), 596 net_wm_state, XA_ATOM, 32, PropModeReplace, 597 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 598 } 599 } 600 601 void NativeWindowSubsystem::X11SetSkipPagerFlag(QWidget *pWidget) 602 { 603 /* Get display: */ 604 Display *pDisplay = QX11Info::display(); 605 606 /* Prepare atoms: */ 607 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 608 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 609 Atom net_wm_state_skip_pager = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_PAGER", True /* only if exists */); 610 611 /* Append resultNetWmState with skip-pager flag if necessary: */ 612 if (!resultNetWmState.contains(net_wm_state_skip_pager)) 613 { 614 resultNetWmState.append(net_wm_state_skip_pager); 615 /* Apply property to widget again: */ 616 XChangeProperty(pDisplay, pWidget->window()->winId(), 617 net_wm_state, XA_ATOM, 32, PropModeReplace, 618 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 619 } 620 } 621 622 void NativeWindowSubsystem::X11SetWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString) 623 { 624 /* Make sure all arguments set: */ 625 AssertReturnVoid(pWidget && !strNameString.isNull() && !strClassString.isNull()); 626 627 /* Define QByteArray objects to make sure data is alive within the scope: */ 628 QByteArray nameByteArray; 629 /* Check the existence of RESOURCE_NAME env. variable and override name string if necessary: */ 630 const char resourceName[] = "RESOURCE_NAME"; 631 if (qEnvironmentVariableIsSet(resourceName)) 632 nameByteArray = qgetenv(resourceName); 633 else 634 nameByteArray = strNameString.toLatin1(); 635 QByteArray classByteArray = strClassString.toLatin1(); 636 637 AssertReturnVoid(nameByteArray.data() && classByteArray.data()); 638 639 XClassHint windowClass; 640 windowClass.res_name = nameByteArray.data(); 641 windowClass.res_class = classByteArray.data(); 642 /* Set WM_CLASS of the window to passed name and class strings: */ 643 XSetClassHint(QX11Info::display(), pWidget->window()->winId(), &windowClass); 644 } 645 646 void NativeWindowSubsystem::X11SetXwaylandMayGrabKeyboardFlag(QWidget *pWidget) 647 { 648 XXSendClientMessage(QX11Info::display(), pWidget->window()->winId(), 649 "_XWAYLAND_MAY_GRAB_KEYBOARD", 1); 650 } -
trunk/src/VBox/Frontends/VirtualBox/src/platform/x11/VBoxUtils-x11.h
r91065 r91066 25 25 #include <QString> 26 26 #include <QVector> 27 #include <QWindow> 27 28 28 29 /* GUI includes: */ … … 49 50 uint m_iCookie; 50 51 }; 52 53 /** X11: XCB size-hints. */ 54 typedef struct 55 { 56 /** User specified flags */ 57 uint32_t flags; 58 /** User-specified position */ 59 int32_t x, y; 60 /** User-specified size */ 61 int32_t width, height; 62 /** Program-specified minimum size */ 63 int32_t min_width, min_height; 64 /** Program-specified maximum size */ 65 int32_t max_width, max_height; 66 /** Program-specified resize increments */ 67 int32_t width_inc, height_inc; 68 /** Program-specified minimum aspect ratios */ 69 int32_t min_aspect_num, min_aspect_den; 70 /** Program-specified maximum aspect ratios */ 71 int32_t max_aspect_num, max_aspect_den; 72 /** Program-specified base size */ 73 int32_t base_width, base_height; 74 /** Program-specified window gravity */ 75 uint32_t win_gravity; 76 } xcb_size_hints_t; 51 77 52 78 /* Namespace for native window sub-system functions: */ … … 76 102 /** X11: Disables/enables Screen Saver through QDBus. */ 77 103 SHARED_LIBRARY_STUFF void X11InhibitUninhibitScrenSaver(bool fInhibit, QVector<X11ScreenSaverInhibitMethod*> &inOutIhibitMethods); 104 105 /** Activates window with certain @a wId, @a fSwitchDesktop if requested. */ 106 bool X11ActivateWindow(WId wId, bool fSwitchDesktop); 107 108 /** X11: Test whether the current window manager supports full screen mode. */ 109 SHARED_LIBRARY_STUFF bool X11SupportsFullScreenMonitorsProtocol(); 110 /** X11: Performs mapping of the passed @a pWidget to host-screen with passed @a uScreenId. */ 111 SHARED_LIBRARY_STUFF bool X11SetFullScreenMonitor(QWidget *pWidget, ulong uScreenId); 112 113 /** X11: Sets _NET_WM_STATE_SKIP_TASKBAR flag for passed @a pWidget. */ 114 SHARED_LIBRARY_STUFF void X11SetSkipTaskBarFlag(QWidget *pWidget); 115 /** X11: Sets _NET_WM_STATE_SKIP_PAGER flag for passed @a pWidget. */ 116 SHARED_LIBRARY_STUFF void X11SetSkipPagerFlag(QWidget *pWidget); 117 118 /** X11: Assigns WM_CLASS property for passed @a pWidget. */ 119 SHARED_LIBRARY_STUFF void X11SetWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString); 120 121 /** X11: Tell the WM we are well behaved wrt Xwayland keyboard-grabs. This will 122 * make the WM turn our grab into a Wayland shortcut inhibition request, 123 * so that e.g. alt+tab will get send to the VM instead of moving the 124 * focus away from the VM. */ 125 SHARED_LIBRARY_STUFF void X11SetXwaylandMayGrabKeyboardFlag(QWidget *pWidget); 78 126 } 79 127 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
r90893 r91066 138 138 strWindowName = QString("VirtualBox Machine UUID: %1").arg(uiCommon().managedVMUuid().toString()); 139 139 /* Assign WM_CLASS property: */ 140 UICommon::setWMClass(this, strWindowName, strWindowClass);140 NativeWindowSubsystem::X11SetWMClass(this, strWindowName, strWindowClass); 141 141 /* Tell the WM we are well behaved wrt Xwayland keyboard-grabs: */ 142 UICommon::setXwaylandMayGrabKeyboardFlag(this);142 NativeWindowSubsystem::X11SetXwaylandMayGrabKeyboardFlag(this); 143 143 #endif 144 144 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp
r90567 r91066 394 394 395 395 /* Determine whether we should use the native full-screen mode: */ 396 const bool fUseNativeFullScreen = UICommon::supportsFullScreenMonitorsProtocolX11() &&397 !gEDataManager->legacyFullscreenModeRequested();396 const bool fUseNativeFullScreen = NativeWindowSubsystem::X11SupportsFullScreenMonitorsProtocol() 397 && !gEDataManager->legacyFullscreenModeRequested(); 398 398 if (fUseNativeFullScreen) 399 399 { 400 400 /* Tell recent window managers which host-screen this window should be mapped to: */ 401 UICommon::setFullScreenMonitorX11(this, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId));401 NativeWindowSubsystem::X11SetFullScreenMonitor(this, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId)); 402 402 } 403 403 -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp
r88862 r91066 797 797 { 798 798 /* Determine whether we should use the native full-screen mode: */ 799 const bool fUseNativeFullScreen = UICommon::supportsFullScreenMonitorsProtocolX11() &&800 !gEDataManager->legacyFullscreenModeRequested();799 const bool fUseNativeFullScreen = NativeWindowSubsystem::X11SupportsFullScreenMonitorsProtocol() 800 && !gEDataManager->legacyFullscreenModeRequested(); 801 801 if (fUseNativeFullScreen) 802 802 { 803 803 /* Tell recent window managers which host-screen this window should be mapped to: */ 804 UICommon::setFullScreenMonitorX11(this, iHostScreen);804 NativeWindowSubsystem::X11SetFullScreenMonitor(this, iHostScreen); 805 805 } 806 806 … … 930 930 #ifdef VBOX_WS_X11 931 931 /* Hide mini-toolbar from taskbar and pager: */ 932 uiCommon().setSkipTaskBarFlag(this);933 uiCommon().setSkipPagerFlag(this);932 NativeWindowSubsystem::X11SetSkipTaskBarFlag(this); 933 NativeWindowSubsystem::X11SetSkipPagerFlag(this); 934 934 #endif 935 935 }
Note:
See TracChangeset
for help on using the changeset viewer.