VirtualBox

Changeset 18578 in vbox


Ignore:
Timestamp:
Mar 31, 2009 2:27:43 PM (15 years ago)
Author:
vboxsync
Message:

HostServices/SharedClipboard: split up a number of functions into a host-specific and an X11-specific part

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp

    r18551 r18578  
    809809
    810810/**
    811  * Initialise the host side of the shared clipboard.
    812  * @todo  This mixes host glue and X11 backend code, separate into two
    813  *        functions.
    814  */
    815 int vboxClipboardInit (void)
     811 * Initialise the X11 backend of the shared clipboard.
     812 * @note  X11 backend code
     813 */
     814int vboxClipboardInitBackend (void)
    816815{
    817816    int rc;
     
    824823         * silently and report success on every call. This is important for VBoxHeadless.
    825824         */
    826         LogRelFunc(("no X11 detected -- host clipboard disabled\n"));
     825        LogRelFunc(("X11 DISPLAY variable not set -- disabling shared clipboard\n"));
    827826        g_fHaveX11 = false;
    828827        return VINF_SUCCESS;
     
    852851    g_fHaveX11 = true;
    853852
    854     LogRel(("Initializing host clipboard service\n"));
    855     RTSemEventCreate(&g_ctxHost.waitForData);
     853    LogRel(("Initializing X11 clipboard backend\n"));
    856854    RTSemEventCreate(&g_ctxX11.waitForData);
    857     RTSemMutexCreate(&g_ctxHost.clipboardMutex);
    858855    rc = vboxClipboardInitX11();
    859856    if (RT_SUCCESS(rc))
     
    862859                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
    863860        if (RT_FAILURE(rc))
    864             LogRel(("Failed to start the host shared clipboard thread.\n"));
     861            LogRel(("Failed to initialise the shared clipboard X11 backend.\n"));
    865862    }
    866863    if (RT_FAILURE(rc))
     864        RTSemEventDestroy(g_ctxX11.waitForData);
     865    return rc;
     866}
     867
     868/**
     869 * Initialise the host side of the shared clipboard.
     870 * @note  Host glue code
     871 */
     872int vboxClipboardInit (void)
     873{
     874    int rc = VINF_SUCCESS;
     875    LogRel(("Initializing host clipboard service\n"));
     876    RTSemEventCreate(&g_ctxHost.waitForData);
     877    RTSemMutexCreate(&g_ctxHost.clipboardMutex);
     878    rc = vboxClipboardInitBackend();
     879    if (RT_FAILURE(rc))
    867880    {
    868881        RTSemEventDestroy(g_ctxHost.waitForData);
    869         RTSemEventDestroy(g_ctxX11.waitForData);
    870882        RTSemMutexDestroy(g_ctxHost.clipboardMutex);
     883        LogRel(("Failed to start the host shared clipboard service.\n"));
    871884    }
    872885    return rc;
     
    874887
    875888/**
    876  * Terminate the host side of the shared clipboard.
    877  * @todo  This mixes host glue and X11 backend code, separate into two
    878  *        functions.
    879  */
    880 void vboxClipboardDestroy (void)
     889 * Terminate the shared clipboard X11 backend.
     890 * @note  X11 backend code
     891 */
     892int vboxClipboardDestroyBackend (void)
    881893{
    882894    int rc, rcThread;
     
    888900     */
    889901    if (!g_fHaveX11)
    890         return;
    891 
    892     LogRel(("vboxClipboardDestroy: shutting down host clipboard\n"));
    893 
    894     /* Drop the reference to the client, in case it is still there.  This will
    895      * cause any outstanding clipboard data requests from X11 to fail
    896      * immediately. */
    897     g_ctxHost.pClient = NULL;
    898     if (g_ctxX11.eOwner == VB)
    899         /* X11 may be waiting for data from VBox.  At this point it is no
    900          * longer going to arrive, and we must release it to allow the event
    901          * loop to terminate.  In this case the buffer where VBox would have
    902          * written the clipboard data will still be empty and we will just
    903          * return "no data" to X11.  Any subsequent attempts to get the data
    904          * from VBox will fail immediately as the client reference is gone. */
    905         RTSemEventSignal(g_ctxHost.waitForData);
     902        return VINF_SUCCESS;
     903
     904    LogRelFunc(("shutting down the shared clipboard X11 backend\n"));
     905
    906906    /* Set the termination flag.  This has been observed to block if it was set
    907907     * during a request for clipboard data coming from X11, so only we do it
     
    922922    if (RT_SUCCESS(rc))
    923923    {
    924         /*
    925          * No one should be waiting on this by now.  Justification:
    926          *  - Case 1: VBox is waiting for data from X11:
    927          *      Not possible, as it would be waiting on this thread.
    928          *  - Case 2: X11 is waiting for data from VBox:
    929          *      Not possible, as we checked that the X11 event thread exited
    930          *      successfully.
    931          */
    932         RTSemEventDestroy(g_ctxHost.waitForData);
     924        /* We can safely destroy this now, as only this thread ever waits
     925         * for it. */
    933926        RTSemEventDestroy(g_ctxX11.waitForData);
    934         RTSemMutexDestroy(g_ctxHost.clipboardMutex);
    935927        AssertRC(rcThread);
    936928    }
     
    938930        LogRel(("vboxClipboardDestroy: rc=%Rrc\n", rc));
    939931    XtCloseDisplay(XtDisplay(g_ctxX11.widget));
    940     LogFlowFunc(("returning.\n"));
    941 }
    942 
    943 /**
    944  * Connect a guest the shared clipboard.
    945  * @todo  This mixes host glue and X11 backend code, separate into two
    946  *        functions.
    947  */
    948 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
    949 {
     932    LogFlowFunc(("returning %Rrc.\n", rc));
     933    return rc;
     934}
     935
     936/**
     937 * Terminate the host side of the shared clipboard.
     938 * @note  host glue code
     939 */
     940void vboxClipboardDestroy (void)
     941{
     942    int rc = VINF_SUCCESS;
     943    LogRelFunc(("shutting down host clipboard\n"));
     944    /* Drop the reference to the client, in case it is still there.  This
     945     * will cause any outstanding clipboard data requests from X11 to fail
     946     * immediately. */
     947    g_ctxHost.pClient = NULL;
     948    /* The backend may be waiting for data from VBox.  At this point it is no
     949     * longer going to arrive, and we must release it to allow the event
     950     * loop to terminate.  In this case the buffer where VBox would have
     951     * written the clipboard data will still be empty and we will just
     952     * return "no data" to the backend.  Any subsequent attempts to get the
     953     * data from VBox will fail immediately as the client reference is gone.
     954     */
     955    /** @note  This has been made unconditional, as it should do no harm
     956     *         even if we are not waiting. */
     957    RTSemEventSignal(g_ctxHost.waitForData);
     958    rc = vboxClipboardDestroyBackend();
     959    if (RT_SUCCESS(rc))
     960    {
     961        /* We can safely destroy these as the backend has exited
     962         * successfully and no other calls from the host code should be
     963         * forthcoming. */
     964        /** @todo  move these two into a frontend proxy object that the
     965         * backend can call. */
     966        /** @todo  can the backend fail to exit successfully?  What then? */
     967        RTSemEventDestroy(g_ctxHost.waitForData);
     968        RTSemMutexDestroy(g_ctxHost.clipboardMutex);
     969    }
     970}
     971
     972/**
     973 * Announce to the X11 backend that we are ready to start.
     974 * @param  owner who is the initial clipboard owner
     975 */
     976int vboxClipboardConnectBackend (enum g_eOwner owner)
     977{
     978    LogFlowFunc(("\n"));
    950979    /*
    951980     * Immediately return if we are not connected to the host X server.
     
    954983        return VINF_SUCCESS;
    955984
    956     LogFlow(("vboxClipboardConnect\n"));
    957 
     985    g_ctxX11.eOwner = owner;
     986    if (owner == X11)
     987        g_ctxX11.notifyVBox = true;
     988    else
     989    {
     990        /** @todo take ownership of the X11 clipboard. */
     991    }
     992    return VINF_SUCCESS;
     993}
     994
     995/**
     996 * Connect a guest to the shared clipboard.
     997 * @note  host glue code
     998 * @note  on the host, we assume that some other application already owns
     999 *        the clipboard and leave ownership to X11.
     1000 */
     1001int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
     1002{
     1003    int rc = VINF_SUCCESS;
     1004    LogFlowFunc(("\n"));
    9581005    /* Only one client is supported for now */
    9591006    AssertLogRelReturn(g_ctxHost.pClient == 0, VERR_NOT_SUPPORTED);
    960 
    9611007    pClient->pCtx = &g_ctxHost;
    9621008    pClient->pCtx->pClient = pClient;
    963     g_ctxX11.eOwner = X11;
    964     g_ctxX11.notifyVBox = true;
    965     return VINF_SUCCESS;
    966 }
    967 
    968 /**
    969  * Synchronise the contents of the host clipboard with the guest, called
    970  * after a save and restore of the guest.
    971  * @todo  This mixes host glue and X11 backend code and calls host frontend
    972  *        APIs.  Separate into two functions.
    973  */
    974 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
    975 {
    976     /*
    977      * Immediately return if we are not connected to the host X server.
    978      */
    979     if (!g_fHaveX11)
    980         return VINF_SUCCESS;
    981 
    982     /* On a Linux host, the guest should never synchronise/cache its clipboard contents, as
    983        we have no way of reliably telling when the host clipboard data changes.  So instead
    984        of synchronising, we tell the guest to empty its clipboard, and we set the cached
    985        flag so that we report formats to the guest next time we poll for them. */
    986     vboxSvcClipboardReportMsg (g_ctxHost.pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
    987     g_ctxX11.notifyVBox = true;
    988 
    989     return VINF_SUCCESS;
    990 }
    991 
    992 /**
    993  * Shut down the shared clipboard service and "disconnect" the guest.
    994  * @todo  This mixes host glue and X11 backend code, separate into two
    995  *        functions.
    996  */
    997 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *)
     1009    /** The pClient pointer is a dummy anyway, as we only support a single
     1010     * client at a time. */
     1011    rc = vboxClipboardConnectBackend(X11 /* initial owner */);
     1012    return rc;
     1013}
     1014
     1015/**
     1016 * Called when the VBox may have fallen out of sync with the backend.
     1017 * @note  X11 backend code
     1018 */
     1019void vboxClipboardRequestSync (void)
    9981020{
    9991021    /*
     
    10021024    if (!g_fHaveX11)
    10031025        return;
    1004 
    1005     LogFlow(("vboxClipboardDisconnect\n"));
    1006 
    1007     RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
    1008     g_ctxHost.pClient = NULL;
     1026    g_ctxX11.notifyVBox = true;
     1027}
     1028
     1029/**
     1030 * Synchronise the contents of the host clipboard with the guest, called
     1031 * after a save and restore of the guest.
     1032 * @note  Host glue code
     1033 */
     1034int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
     1035{
     1036
     1037    /* On a Linux host, the guest should never synchronise/cache its
     1038     * clipboard contents, as we have no way of reliably telling when the
     1039     * host clipboard data changes.  So instead of synchronising, we tell
     1040     * the guest to empty its clipboard, and we set the cached flag so that
     1041     * we report formats to the guest next time we poll for them. */
     1042    /** @note  This has been changed so that the message is sent even if
     1043     *         X11 is not available. */
     1044    vboxSvcClipboardReportMsg (g_ctxHost.pClient,
     1045                               VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
     1046    vboxClipboardRequestSync();
     1047
     1048    return VINF_SUCCESS;
     1049}
     1050
     1051/**
     1052 * Shut down the shared clipboard service and "disconnect" the guest.
     1053 * @todo  This mixes host glue and X11 backend code, separate into two
     1054 *        functions.
     1055 */
     1056void vboxClipboardDisconnectBackend (void)
     1057{
     1058    /*
     1059     * Immediately return if we are not connected to the host X server.
     1060     */
     1061    if (!g_fHaveX11)
     1062        return;
     1063
    10091064    g_ctxX11.eOwner = NONE;
    10101065    g_ctxX11.X11TextFormat = INVALID;
    10111066    g_ctxX11.X11BitmapFormat = INVALID;
     1067}
     1068
     1069/**
     1070 * Shut down the shared clipboard service and "disconnect" the guest.
     1071 * @todo  This mixes host glue and X11 backend code, separate into two
     1072 *        functions.
     1073 */
     1074void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *)
     1075{
     1076    LogFlow(("vboxClipboardDisconnect\n"));
     1077
     1078    RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
     1079    g_ctxHost.pClient = NULL;
     1080    vboxClipboardDisconnectBackend();
    10121081    RTSemMutexRelease(g_ctxHost.clipboardMutex);
    10131082}
     
    14811550 * VBox is taking possession of the shared clipboard.
    14821551 *
    1483  * @param pClient    Context data for the guest system
    14841552 * @param u32Formats Clipboard formats the guest is offering
    1485  * @note    Called by the HGCM clipboard service
    1486  * @thread  HGCM clipboard service thread
    1487  */
    1488 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats)
     1553 * @note  X11 backend code
     1554 */
     1555void vboxClipboardFormatAnnounceBackend (uint32_t u32Formats)
    14891556{
    14901557    /*
     
    15301597
    15311598/**
     1599 * VBox is taking possession of the shared clipboard.
     1600 *
     1601 * @param pClient    Context data for the guest system
     1602 * @param u32Formats Clipboard formats the guest is offering
     1603 * @note  Host glue code
     1604 */
     1605void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats)
     1606{
     1607    vboxClipboardFormatAnnounceBackend (u32Formats);
     1608}
     1609
     1610/**
     1611 * Called when VBox wants to read the X11 clipboard.
     1612 *
     1613 * @param  pClient   Context information about the guest VM
     1614 * @param  u32Format The format that the guest would like to receive the data in
     1615 * @param  pv        Where to write the data to
     1616 * @param  cb        The size of the buffer to write the data to
     1617 * @param  pcbActual Where to write the actual size of the written data
     1618 * @note   X11 backend code
     1619 */
     1620int vboxClipboardReadDataBackend (uint32_t u32Format,
     1621                                  VBOXCLIPBOARDREQUEST *pRequest)
     1622{
     1623    /*
     1624     * Immediately return if we are not connected to the host X server.
     1625     */
     1626    if (!g_fHaveX11)
     1627    {
     1628        /* no data available */
     1629        *pRequest->pcbActual = 0;
     1630        return VINF_SUCCESS;
     1631    }
     1632
     1633    LogFlowFunc (("u32Format = %d, cb = %d\n", u32Format, pRequest->cb));
     1634
     1635    /*
     1636     * The guest wants to read data in the given format.
     1637     */
     1638    if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     1639    {
     1640        if (g_ctxX11.X11TextFormat == INVALID)
     1641        {
     1642            /* No data available. */
     1643            *pRequest->pcbActual = 0;
     1644            return VERR_NO_DATA;  /* The guest thinks we have data and we don't */
     1645        }
     1646        /* Initially set the size of the data read to zero in case we fail
     1647         * somewhere. */
     1648        *pRequest->pcbActual = 0;
     1649        /* Send out a request for the data to the current clipboard owner */
     1650        XtGetSelectionValue(g_ctxX11.widget, g_ctxX11.atomClipboard,
     1651                            g_ctxX11.atomX11TextFormat,
     1652                            vboxClipboardGetDataFromX11,
     1653                            reinterpret_cast<XtPointer>(pRequest),
     1654                            CurrentTime);
     1655        /* When the data arrives, the vboxClipboardGetDataFromX11 callback will be called.  The
     1656           callback will signal the event semaphore when it has processed the data for us. */
     1657
     1658        int rc = RTSemEventWait(g_ctxX11.waitForData, RT_INDEFINITE_WAIT);
     1659        if (RT_FAILURE(rc))
     1660            return rc;
     1661    }
     1662    else
     1663    {
     1664        return VERR_NOT_IMPLEMENTED;
     1665    }
     1666    return VINF_SUCCESS;
     1667}
     1668
     1669/**
    15321670 * Called when VBox wants to read the X11 clipboard.
    15331671 *
     
    15381676 * @param  pcbActual Where to write the actual size of the written data
    15391677 * @note   Host glue code
    1540  * @todo   Separate this into a host and an X11-specific function
    15411678 */
    15421679int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient,
     
    15441681                           uint32_t *pcbActual)
    15451682{
     1683    int rc = VINF_SUCCESS;
    15461684    VBOXCLIPBOARDREQUEST request;
    1547     /*
    1548      * Immediately return if we are not connected to the host X server.
    1549      */
    1550     if (!g_fHaveX11)
    1551     {
    1552         /* no data available */
    1553         *pcbActual = 0;
    1554         return VINF_SUCCESS;
    1555     }
    1556 
    1557     LogFlowFunc (("u32Format = %d, cb = %d\n", u32Format, cb));
    1558 
    1559     /*
    1560      * The guest wants to read data in the given format.
    1561      */
    1562     if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    1563     {
    1564         if (g_ctxX11.X11TextFormat == INVALID)
    1565         {
    1566             /* No data available. */
    1567             *pcbActual = 0;
    1568             return VERR_NO_DATA;  /* The guest thinks we have data and we don't */
    1569         }
    1570         /* No one else (VBox or X11) should currently be waiting.  The first because
    1571          * requests from VBox are serialised and the second because X11 previously
    1572          * grabbed the clipboard, so it should not be waiting for data from us. */
    1573         AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctxHost.waiter, VB, NONE), VERR_DEADLOCK);
    1574         request.pv = pv;
    1575         request.cb = cb;
    1576         request.pcbActual = pcbActual;
    1577         /* Initially set the size of the data read to zero in case we fail
    1578          * somewhere. */
    1579         *pcbActual = 0;
    1580         /* Send out a request for the data to the current clipboard owner */
    1581         XtGetSelectionValue(g_ctxX11.widget, g_ctxX11.atomClipboard,
    1582                             g_ctxX11.atomX11TextFormat,
    1583                             vboxClipboardGetDataFromX11,
    1584                             reinterpret_cast<XtPointer>(&request),
    1585                             CurrentTime);
    1586         /* When the data arrives, the vboxClipboardGetDataFromX11 callback will be called.  The
    1587            callback will signal the event semaphore when it has processed the data for us. */
    1588 
    1589         int rc = RTSemEventWait(g_ctxX11.waitForData, RT_INDEFINITE_WAIT);
    1590         if (RT_FAILURE(rc))
    1591         {
    1592             g_ctxHost.waiter = NONE;
    1593             return rc;
    1594         }
    1595         g_ctxHost.waiter = NONE;
    1596     }
    1597     else
    1598     {
    1599         return VERR_NOT_IMPLEMENTED;
    1600     }
    1601     return VINF_SUCCESS;
     1685    /* No one else (VBox or X11) should currently be waiting.  The first
     1686     * because requests from VBox are serialised and the second because X11
     1687     * previously grabbed the clipboard, so it should not be waiting for
     1688     * data from us. */
     1689    AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctxHost.waiter, VB, NONE),
     1690                        VERR_DEADLOCK);
     1691    request.pv = pv;
     1692    request.cb = cb;
     1693    request.pcbActual = pcbActual;
     1694    rc = vboxClipboardReadDataBackend(u32Format, &request);
     1695    g_ctxHost.waiter = NONE;
     1696    return rc;
    16021697}
    16031698
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