VirtualBox

Changeset 51243 in vbox


Ignore:
Timestamp:
May 13, 2014 2:16:56 PM (11 years ago)
Author:
vboxsync
Message:

Additions/x11/VBoxClient: make VBoxClient --display use the new interface to the X.Org video driver.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/display.cpp

    r50432 r51243  
    2424
    2525#include <X11/Xlib.h>
     26#include <X11/Xatom.h>
    2627#include <X11/cursorfont.h>
    27 #include <X11/extensions/Xrandr.h>
    2828
    2929#include <iprt/assert.h>
    3030#include <iprt/err.h>
    3131#include <iprt/file.h>
     32#include <iprt/mem.h>
    3233#include <iprt/string.h>
    3334#include <iprt/thread.h>
     
    3839#include "VBoxClient.h"
    3940
     41/** Exit with a fatal error.
     42 * @todo Make this application global. */
     43#define FatalError(format) \
     44do { \
     45    char *pszMessage = RTStrAPrintf2 format; \
     46    LogRel(format); \
     47    doFatalError(pszMessage); \
     48} while(0)
     49
     50static void doFatalError(char *pszMessage)
     51{
     52    char *pszCommand;
     53    if (pszMessage)
     54    {
     55        pszCommand = RTStrAPrintf2("notify-send \"VBoxClient: %s\"",
     56                                   pszMessage);
     57        if (pszCommand)
     58            system(pszCommand);
     59    }
     60    exit(1);
     61}
     62
    4063/** Tell the VBoxGuest driver we no longer want any events and tell the host
    4164 * we no longer support any capabilities. */
    4265static int disableEventsAndCaps()
    4366{
    44     int rc, rc2;
    45     rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
    46     rc2 = VbglR3SetMouseStatus(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
    47     rc = RT_FAILURE(rc) ? rc : rc2;
    48     rc2 = VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
    49     rc = RT_FAILURE(rc) ? rc : rc2;
    50     return rc;
     67    int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
     68    if (RT_FAILURE(rc))
     69        FatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));
     70    rc = VbglR3SetMouseStatus(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
     71    if (RT_FAILURE(rc))
     72        FatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
     73    rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
     74                                | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     75    if (RT_FAILURE(rc))
     76        FatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
     77    return VINF_SUCCESS;
    5178}
    5279
    5380/** Tell the VBoxGuest driver which events we want and tell the host which
    5481 * capabilities we support. */
    55 static int enableEventsAndCaps(Display *pDisplay, bool fFirstTime)
    56 {
    57     int iDummy, rc;
    58     uint32_t fFilterMask = VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
    59     uint32_t fCapabilities = 0;
    60     if (XRRQueryExtension(pDisplay, &iDummy, &iDummy))
    61     {
    62         fFilterMask |= VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
    63         fCapabilities |= VMMDEV_GUEST_SUPPORTS_GRAPHICS;
    64     }
    65     else if (fFirstTime)
    66         LogRel(("VBoxClient: guest does not support dynamic resizing.\n"));
    67     rc = VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
    68     if (RT_SUCCESS(rc))
    69         rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0);
    70     /** @todo Make sure that VBoxGuest understands
    71      * VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR as a "negative" capability: if we
    72      * don't advertise it it means we *can* switch to a software cursor and
    73      * back. */
    74     if (RT_SUCCESS(rc))
    75         rc = VbglR3SetMouseStatus(0);
    76     if (RT_FAILURE(rc))
    77         disableEventsAndCaps();
    78     return rc;
    79 }
    80 
    81 /**
    82  * This method first resets the current resolution using RandR to wake up
    83  * the graphics driver, then sets the resolution requested if it is among
    84  * those offered by the driver.
    85  */
    86 static void setSize(Display *pDisplay, uint32_t cx, uint32_t cy)
    87 {
    88     XRRScreenConfiguration *pConfig;
    89     XRRScreenSize *pSizes;
    90     int cSizes;
    91     pConfig = XRRGetScreenInfo(pDisplay, DefaultRootWindow(pDisplay));
    92     /* Reset the current mode */
    93     LogRelFlowFunc(("Setting size %ux%u\n", cx, cy));
    94     if (pConfig)
    95     {
    96         pSizes = XRRConfigSizes(pConfig, &cSizes);
    97         unsigned uDist = UINT32_MAX;
    98         int iMode = -1;
    99         for (int i = 0; i < cSizes; ++i)
    100         {
    101 #define VBCL_SQUARE(x) (x) * (x)
    102             unsigned uThisDist =   VBCL_SQUARE(pSizes[i].width - cx)
    103                                  + VBCL_SQUARE(pSizes[i].height - cy);
    104             LogRelFlowFunc(("Found size %dx%d, distance %u\n", pSizes[i].width,
    105                          pSizes[i].height, uThisDist));
    106 #undef VBCL_SQUARE
    107             if (uThisDist < uDist)
    108             {
    109                 uDist = uThisDist;
    110                 iMode = i;
    111             }
    112         }
    113         if (iMode >= 0)
    114         {
    115             Time config_timestamp = 0;
    116             XRRConfigTimes(pConfig, &config_timestamp);
    117             LogRelFlowFunc(("Setting new size %d\n", iMode));
    118             XRRSetScreenConfig(pDisplay, pConfig,
    119                                DefaultRootWindow(pDisplay), iMode,
    120                                RR_Rotate_0, config_timestamp);
    121         }
    122         XRRFreeScreenConfigInfo(pConfig);
    123     }
     82static int enableEventsAndCaps(Display *pDisplay)
     83{
     84    int rc = VbglR3CtlFilterMask(  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
     85                                 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
     86    if (RT_FAILURE(rc))
     87        FatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));
     88    rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0);
     89    if (RT_FAILURE(rc))
     90        FatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));
     91    rc = VbglR3SetMouseStatus(0);
     92    if (RT_FAILURE(rc))
     93        FatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));
     94    return VINF_SUCCESS;
    12495}
    12596
     
    133104static void runDisplay(Display *pDisplay)
    134105{
    135     LogRelFlowFunc(("\n"));
     106    int status, rc;
     107    char szCommand[256];
    136108    Cursor hClockCursor = XCreateFontCursor(pDisplay, XC_watch);
    137109    Cursor hArrowCursor = XCreateFontCursor(pDisplay, XC_left_ptr);
    138     int RRMaj, RRMin;
    139     bool fExtDispReqSupport = true;
    140     if (!XRRQueryVersion(pDisplay, &RRMaj, &RRMin))
    141         RRMin = 0;
     110    LogRelFlowFunc(("\n"));
     111    bool fExtDispReqSupport = true, fHaveRandR12 = false;
    142112    const char *pcszXrandr = "xrandr";
    143113    if (RTFileExists("/usr/X11/bin/xrandr"))
    144114        pcszXrandr = "/usr/X11/bin/xrandr";
     115    status = system(pcszXrandr);
     116    if (WEXITSTATUS(status) != 0)  /* Utility or extension not available. */
     117        FatalError(("Failed to execute the xrandr utility.\n"));
     118    RTStrPrintf(szCommand, sizeof(szCommand), "%s --q12", pcszXrandr);
     119    status = system(szCommand);
     120    if (WEXITSTATUS(status) == 0)
     121        fHaveRandR12 = true;
    145122    while (true)
    146123    {
    147         uint32_t fEvents = 0, cx = 0, cy = 0, cBits = 0, iDisplay = 0, cxOrg = 0, cyOrg = 0;
    148         bool fEnabled = false;
    149         int rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
     124        uint32_t fEvents;
     125        /** The size of our array of size hints. */
     126        unsigned cSizeHints = 0;
     127        /** Array of size hints.  Large enough to hold the highest display
     128         * number we have had a hint for so far, reallocated when a higher one
     129         * comes.  Zero means no hint for that display. */
     130        long *paSizeHints = NULL;
     131        do
     132            rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
    150133                                 | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
    151134                                 RT_INDEFINITE_WAIT, &fEvents);
    152         if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED)  /* VERR_NO_MEMORY? */
     135        while(rc == VERR_INTERRUPTED);
     136        if (RT_FAILURE(rc))  /* VERR_NO_MEMORY? */
     137            FatalError(("event wait failed, rc=%Rrc\n", rc));
     138        if (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
    153139        {
    154             LogRelFunc(("VBoxClient: VbglR3WaitEvent failed, rc=%Rrc\n", rc));
    155             VBoxClient::CleanUp();
     140            /* Jiggle the mouse pointer to trigger a switch to a software
     141             * cursor if necessary. */
     142            XGrabPointer(pDisplay,
     143                         DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
     144                         GrabModeAsync, None, hClockCursor, CurrentTime);
     145            XFlush(pDisplay);
     146            XGrabPointer(pDisplay,
     147                         DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
     148                         GrabModeAsync, None, hArrowCursor, CurrentTime);
     149            XFlush(pDisplay);
     150            XUngrabPointer(pDisplay, CurrentTime);
     151            XFlush(pDisplay);
    156152        }
    157         /* Jiggle the mouse pointer to wake up the driver. */
    158         XGrabPointer(pDisplay,
    159                      DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
    160                      GrabModeAsync, None, hClockCursor, CurrentTime);
    161         XFlush(pDisplay);
    162         XGrabPointer(pDisplay,
    163                      DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
    164                      GrabModeAsync, None, hArrowCursor, CurrentTime);
    165         XFlush(pDisplay);
    166         XUngrabPointer(pDisplay, CurrentTime);
    167         XFlush(pDisplay);
    168         /* And if it is a size hint, set the new size now that the video
    169          * driver has had a chance to update its list. */
    170         if (RT_SUCCESS(rc) && (fEvents & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST))
     153        /* And if it is a size hint, set the new size. */
     154        if (fEvents & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
    171155        {
    172             int rc2 = VbglR3GetDisplayChangeRequestEx(&cx, &cy, &cBits,
    173                                                       &iDisplay, &cxOrg, &cyOrg, &fEnabled, true);
    174             /* Extended display version not supported on host */
    175             if (RT_FAILURE(rc2))
    176             {
    177                 LogRel(("GetDisplayChangeReq Extended Version not supported.  "
    178                         "Trying for Normal Mode with cx=%d & cy=%d\n", cx, cy));
    179                 fExtDispReqSupport = false;
    180                 rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits, &iDisplay, true);
     156            uint32_t cx = 0, cy = 0, cBits = 0, iDisplay = 0, cxOrg = 0,
     157                     cyOrg = 0;
     158            bool fEnabled = false;
     159            if (fExtDispReqSupport)
     160            {
     161                int rc2 = VbglR3GetDisplayChangeRequestEx(&cx, &cy, &cBits,
     162                                                          &iDisplay, &cxOrg,
     163                                                          &cyOrg, &fEnabled,
     164                                                          true);
     165                /* Extended display version not supported on host */
     166                if (RT_FAILURE(rc2))
     167                {
     168                    if (rc2 != VERR_NOT_IMPLEMENTED)
     169                        FatalError(("Failed to get display change request, rc=%Rrc\n",
     170                                    rc));
     171                    LogRel(("Extended display change request not supported.\n"));
     172                    fExtDispReqSupport = false;
     173                }
     174                else
     175                    LogRelFlowFunc(("Got Extended Param from Host cx=%d, cy=%d, bpp=%d, iDisp=%d, OrgX=%d, OrgY=%d Enb=%d\n",
     176                                    cx, cy, cBits, iDisplay, cxOrg, cyOrg,
     177                                    fEnabled));
     178            }
     179            if (!fExtDispReqSupport)
     180                rc = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits, &iDisplay,
     181                                                   true);
     182            if (RT_FAILURE(rc))
     183                FatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));
     184            if (iDisplay > INT32_MAX)
     185                FatalError(("Received a hint for too high display number %u\n",
     186                            (unsigned) iDisplay));
     187            if (iDisplay >= cSizeHints)
     188            {
     189                uint32_t i;
     190
     191                paSizeHints = (long *)RTMemRealloc(paSizeHints,
     192                                                     (iDisplay + 1)
     193                                                   * sizeof(*paSizeHints));
     194                if (!paSizeHints)
     195                    FatalError(("Failed to re-allocate size hint memory.\n"));
     196                for (i = cSizeHints; i < iDisplay + 1; ++i)
     197                    paSizeHints[i] = 0;
     198                cSizeHints = iDisplay + 1;
     199            }
     200            if ((!fExtDispReqSupport || fEnabled) && cx != 0 && cy != 0)
     201            {
     202                paSizeHints[iDisplay] = (cx & 0xffff) << 16 | (cy & 0xffff);
     203                XChangeProperty(pDisplay, DefaultRootWindow(pDisplay),
     204                                XInternAtom(pDisplay, "VBOX_SIZE_HINTS", 0),
     205                                XA_INTEGER, 32, PropModeReplace,
     206                                (unsigned char *)paSizeHints, cSizeHints);
     207                XFlush(pDisplay);
     208            }
     209            if (!fHaveRandR12)
     210            {
     211                RTStrPrintf(szCommand, sizeof(szCommand),
     212                            "%s -s %ux%u", pcszXrandr, cx, cy);
     213                status = system(szCommand);
     214                if (WEXITSTATUS(status) != 0)
     215                    FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    181216            }
    182217            else
    183                 LogRelFlowFunc(("Got Extended Param from Host cx=%d, cy=%d, bpp=%d, iDisp=%d, "
    184                                 "OrgX=%d, OrgY=%d Enb=%d\n", cx, cy, cBits, iDisplay,
    185                                 cxOrg, cyOrg, fEnabled));
    186             /* If we are not stopping, sleep for a bit to avoid using up
    187                 too much CPU while retrying. */
    188             if (RT_FAILURE(rc2))
    189                 RTThreadYield();
    190             else
    191                 if (RRMin < 2)
    192                     setSize(pDisplay, cx, cy);
    193                 else
     218            {
     219                if (fExtDispReqSupport && fEnabled)
    194220                {
    195                     char szCommand[256];
    196                     if (fExtDispReqSupport)
    197                     {
    198                         if (fEnabled)
    199                         {
    200                             if (cx != 0 && cy != 0)
    201                             {
    202                                 RTStrPrintf(szCommand, sizeof(szCommand),
    203                                             "%s --output VGA-%u --set VBOX_MODE %d",
    204                                             pcszXrandr, iDisplay,
    205                                             (cx & 0xffff) << 16 | (cy & 0xffff));
    206                                 system(szCommand);
    207                             }
    208                             /* Extended Display support possible . Secondary monitor position supported */
    209                             if (cxOrg != 0 || cyOrg != 0)
    210                             {
    211                                 RTStrPrintf(szCommand, sizeof(szCommand),
    212                                             "%s --output VGA-%u --auto --pos %dx%d",
    213                                             pcszXrandr, iDisplay, cxOrg, cyOrg);
    214                                 system(szCommand);
    215                             }
    216                             RTStrPrintf(szCommand, sizeof(szCommand),
    217                                         "%s --output VGA-%u --preferred",
    218                                         pcszXrandr, iDisplay);
    219                             system(szCommand);
    220                         }
    221                         else /* disable the virtual monitor */
    222                         {
    223                             RTStrPrintf(szCommand, sizeof(szCommand),
    224                                         "%s --output VGA-%u --off",
    225                                          pcszXrandr, iDisplay);
    226                             system(szCommand);
    227                         }
    228                     }
    229                     else /* Extended display support not possible */
    230                     {
    231                         if (cx != 0 && cy != 0)
    232                         {
    233                             RTStrPrintf(szCommand, sizeof(szCommand),
    234                                         "%s --output VGA-%u --set VBOX_MODE %d",
    235                                         pcszXrandr, iDisplay,
    236                                         (cx & 0xffff) << 16 | (cy & 0xffff));
    237                             system(szCommand);
    238                             RTStrPrintf(szCommand, sizeof(szCommand),
    239                                         "%s --output VGA-%u --preferred",
    240                                         pcszXrandr, iDisplay);
    241                             system(szCommand);
    242                         }
    243                     }
    244 
     221                    /* Extended Display support possible . Secondary monitor
     222                     * position supported */
     223                    RTStrPrintf(szCommand, sizeof(szCommand),
     224                                "%s --output VGA-%u --auto --pos %dx%d",
     225                                pcszXrandr, iDisplay, cxOrg, cyOrg);
     226                    status = system(szCommand);
     227                    if (WEXITSTATUS(status) != 0)
     228                        FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    245229                }
     230                if ((!fExtDispReqSupport || fEnabled) && cx != 0 && cy != 0)
     231                {
     232                    RTStrPrintf(szCommand, sizeof(szCommand),
     233                                "%s --output VGA-%u --preferred",
     234                                pcszXrandr, iDisplay);
     235                    status = system(szCommand);
     236                    if (WEXITSTATUS(status) != 0)
     237                        FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     238                }
     239                if (fExtDispReqSupport && !fEnabled)
     240                {
     241                    /* disable the virtual monitor */
     242                    RTStrPrintf(szCommand, sizeof(szCommand),
     243                                "%s --output VGA-%u --off",
     244                                 pcszXrandr, iDisplay);
     245                    status = system(szCommand);
     246                    if (WEXITSTATUS(status) != 0)
     247                        FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     248                }
     249            }
    246250        }
    247251    }
     
    266270        if (!mDisplay)
    267271            return VERR_NOT_FOUND;
    268         rc = enableEventsAndCaps(mDisplay, true);
     272        rc = enableEventsAndCaps(mDisplay);
    269273        if (RT_SUCCESS(rc))
    270274            mfInit = true;
     
    288292        if (!mfInit)
    289293            return VERR_WRONG_ORDER;
    290         return enableEventsAndCaps(mDisplay, false);
     294        return enableEventsAndCaps(mDisplay);
    291295    }
    292296    virtual void cleanup()
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