VirtualBox

Changeset 91066 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 1, 2021 3:56:33 PM (3 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:10067: Moving X11 stuff to VBoxUtils-x11.

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  
    4343#endif
    4444#ifdef VBOX_WS_X11
    45 # include <QScreen>
    46 # include <QScrollBar>
    47 # include <QTextBrowser>
    4845# include <QX11Info>
    4946#endif
     
    127124#include <iprt/stream.h>
    128125#include <iprt/system.h>
    129 #ifdef VBOX_WS_X11
    130 # include <iprt/mem.h>
    131 #endif
    132126#include <VBox/sup.h>
    133127#include <VBox/VBoxOGL.h>
     
    142136# include <iprt/win/shlobj.h>
    143137#endif
    144 #ifdef VBOX_WS_X11
    145 # include <xcb/xcb.h>
    146 #endif
    147138
    148139/* External includes: */
     
    150141#ifdef VBOX_WS_MAC
    151142# include <sys/utsname.h>
    152 #endif
    153 #ifdef VBOX_WS_X11
    154 // WORKAROUND:
    155 // typedef CARD8 BOOL in Xmd.h conflicts with #define BOOL PRBool
    156 // in COMDefs.h. A better fix would be to isolate X11-specific
    157 // stuff by placing XX* helpers below to a separate source file.
    158 # undef BOOL
    159 # 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 PRBool
    166143#endif
    167144
     
    15181495}
    15191496
    1520 #ifdef VBOX_WS_X11
    1521 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 
    15451497/* static */
    15461498void UICommon::setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h)
     
    16091561}
    16101562
    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 #endif
    1665 
    16661563/* static */
    16671564bool UICommon::activateWindow(WId wId, bool fSwitchDesktop /* = true */)
     
    16831580#elif defined(VBOX_WS_X11)
    16841581
    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);
    17221583
    17231584#else
     
    17351596    return fResult;
    17361597}
    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 find
    1745      * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all
    1746      * interesting window managers. If this fails for a user when you think it should succeed
    1747      * 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 == None
    1777         || 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     else
    1949         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 */
    19681598
    19691599/* static */
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.h

    r91057 r91066  
    4545/* Other VBox includes: */
    4646#include "VBox/com/Guid.h"
    47 
    48 /* Other includes: */
    49 #ifdef VBOX_WS_X11
    50 # include <X11/Xdefs.h>
    51 #endif
    5247
    5348/* Forward declarations: */
     
    218213
    219214#ifdef VBOX_WS_X11
     215        /** X11: Returns the type of the Window Manager we are running under. */
     216        X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; }
    220217        /** X11: Returns whether the Window Manager we are running under is composition one. */
    221218        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; }
    224219#endif
    225220    /** @} */
     
    342337        /** Activates the specified window with given @a wId. Can @a fSwitchDesktop if requested. */
    343338        static bool activateWindow(WId wId, bool fSwitchDesktop = true);
    344 
    345 #ifdef VBOX_WS_X11
    346         /** 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 will
    365           * 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 the
    367           * focus away from the VM. */
    368         static void setXwaylandMayGrabKeyboardFlag(QWidget *pWidget);
    369 #endif /* VBOX_WS_X11 */
    370339
    371340        /** Assigns minimum @a pSpinBox to correspond to @a cCount digits. */
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManager.cpp

    r91009 r91066  
    19831983#ifdef VBOX_WS_X11
    19841984    /* 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");
    19861986#endif
    19871987
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/x11/VBoxUtils-x11.cpp

    r91065 r91066  
    2424#include <QtXml/QDomElement>
    2525#include <QX11Info>
     26#include <QWidget>
    2627
    2728/* GUI includes: */
     
    2930
    3031/* Other VBox includes: */
     32#include <iprt/assert.h>
    3133#include <VBox/log.h>
    3234
     
    336338    }
    337339}
     340
     341char *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
     362bool 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
     392bool 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
     431bool 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
     493bool 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
     502QVector<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?
     546bool 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
     558void 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
     580void 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
     601void 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
     622void 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
     646void 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  
    2525#include <QString>
    2626#include <QVector>
     27#include <QWindow>
    2728
    2829/* GUI includes: */
     
    4950    uint     m_iCookie;
    5051};
     52
     53/** X11: XCB size-hints. */
     54typedef 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;
    5177
    5278/* Namespace for native window sub-system functions: */
     
    76102    /** X11: Disables/enables Screen Saver through QDBus. */
    77103    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);
    78126}
    79127
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp

    r90893 r91066  
    138138        strWindowName = QString("VirtualBox Machine UUID: %1").arg(uiCommon().managedVMUuid().toString());
    139139    /* Assign WM_CLASS property: */
    140     UICommon::setWMClass(this, strWindowName, strWindowClass);
     140    NativeWindowSubsystem::X11SetWMClass(this, strWindowName, strWindowClass);
    141141    /* Tell the WM we are well behaved wrt Xwayland keyboard-grabs: */
    142     UICommon::setXwaylandMayGrabKeyboardFlag(this);
     142    NativeWindowSubsystem::X11SetXwaylandMayGrabKeyboardFlag(this);
    143143#endif
    144144}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp

    r90567 r91066  
    394394
    395395    /* 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();
    398398    if (fUseNativeFullScreen)
    399399    {
    400400        /* 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));
    402402    }
    403403
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp

    r88862 r91066  
    797797        {
    798798            /* 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();
    801801            if (fUseNativeFullScreen)
    802802            {
    803803                /* Tell recent window managers which host-screen this window should be mapped to: */
    804                 UICommon::setFullScreenMonitorX11(this, iHostScreen);
     804                NativeWindowSubsystem::X11SetFullScreenMonitor(this, iHostScreen);
    805805            }
    806806
     
    930930#ifdef VBOX_WS_X11
    931931    /* Hide mini-toolbar from taskbar and pager: */
    932     uiCommon().setSkipTaskBarFlag(this);
    933     uiCommon().setSkipPagerFlag(this);
     932    NativeWindowSubsystem::X11SetSkipTaskBarFlag(this);
     933    NativeWindowSubsystem::X11SetSkipPagerFlag(this);
    934934#endif
    935935}
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