VirtualBox

Changeset 92158 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Oct 30, 2021 12:06:36 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
147981
Message:

ValKit/ClipUtil: Some X11 bits. bugref:10133

Location:
trunk/src/VBox/ValidationKit/utils/clipboard
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/clipboard/ClipUtil.cpp

    r92026 r92158  
    5050#include <iprt/zero.h>
    5151
    52 #ifdef RT_OS_WINDOWS
     52#ifdef RT_OS_DARWIN
     53/** @todo   */
     54#elif defined(RT_OS_WINDOWS)
    5355# include <iprt/nt/nt-and-windows.h>
     56#elif !defined(RT_OS_OS2)
     57# include <X11/Xlib.h>
     58# include <X11/Xatom.h>
    5459#endif
    5560
     
    6065#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) || defined(RT_OS_DARWIN)
    6166# undef MULTI_TARGET_CLIPBOARD
     67# undef CU_X11
    6268#else
    6369# define MULTI_TARGET_CLIPBOARD
     70# define CU_X11
    6471#endif
    6572
     
    9299    CFStringRef *hStrFormat;
    93100#else
     101    /** The X11 atom for the format. */
     102    Atom        uAtom;
     103    /** The X11 atom name if uAtom must be termined dynamically. */
     104    const char *pszAtomName;
    94105    /** @todo X11 */
    95106#endif
     
    105116/** Convert to/from UTF-8.  */
    106117#define CLIPUTILFORMAT_F_CONVERT_UTF8       RT_BIT_32(0)
    107 
    108 
     118/** Ad hoc entry.  */
     119#define CLIPUTILFORMAT_F_AD_HOC             RT_BIT_32(1)
     120
     121
     122#ifdef MULTI_TARGET_CLIPBOARD
    109123/**
    110124 * Clipboard target descriptor.
     
    114128    /** Target name.   */
    115129    const char *pszName;
     130    /** The X11 atom for the target. */
     131    Atom        uAtom;
     132    /** The X11 atom name if uAtom must be termined dynamically. */
     133    const char *pszAtomName;
    116134    /** Description. */
    117135    const char *pszDesc;
     
    119137/** Pointer to clipboard target descriptor. */
    120138typedef CLIPUTILTARGET const *PCCLIPUTILTARGET;
     139#endif /* MULTI_TARGET_CLIPBOARD */
    121140
    122141
     
    146165
    147166/** Format descriptors. */
    148 static const CLIPUTILFORMAT g_aFormats[] =
     167static CLIPUTILFORMAT g_aFormats[] =
    149168{
    150169#if defined(RT_OS_WINDOWS)
     
    165184#else
    166185    /** @todo X11   */
    167     { "text/utf-8",                        "UTF-8 text", 0 },
     186    { "text/utf-8",                 None, "UTF8_STRING",       "UTF-8 text", 0 },
    168187#endif
    169188};
    170189
     190#ifdef MULTI_TARGET_CLIPBOARD
    171191/** Target descriptors. */
    172 static const CLIPUTILTARGET g_aTargets[] =
    173 {
    174 #ifndef MULTI_TARGET_CLIPBOARD
    175     { "default", "placeholder" }
    176 #else
    177     { "default", "default" }, /** @todo X11 */
    178 #endif
     192static CLIPUTILTARGET g_aTargets[] =
     193{
     194    { "clipboard", 0, "CLIPBOARD",     "XA_CLIPBOARD: The clipboard (default)" },
     195    { "primary",   XA_PRIMARY,   NULL, "XA_PRIMARY:   Primary selected text (middle mouse button)" },
     196    { "secondary", XA_SECONDARY, NULL, "XA_SECONDARY: Secondary selected text (with ctrl)" },
    179197};
     198
     199/** The current clipboard target. */
     200static CLIPUTILTARGET *g_pTarget = &g_aTargets[0];
     201#endif /* MULTI_TARGET_CLIPBOARD */
    180202
    181203/** The -v/-q state. */
    182204static unsigned g_uVerbosity = 1;
    183205
    184 #ifdef RT_OS_WINDOWS
     206#ifdef RT_OS_DARWIN
     207
     208#elif defined(RT_OS_OS2)
     209/** Anchorblock handle. */
     210static HAB      g_hOs2Hab = NULLHANDLE;
     211/** The message queue handle.   */
     212static HMQ      g_hOs2MsgQueue = NULLHANDLE;
     213/** Set if we've opened the clipboard. */
     214static bool     g_fOs2OpenedClipboard = false;
     215
     216#elif defined(RT_OS_WINDOWS)
     217/** Set if we've opened the clipboard. */
    185218static bool     g_fOpenedClipboard = false;
    186 #endif
    187 
    188 
    189 /**
    190  * Gets a format descriptor, complaining if unknown format.
     219
     220#else
     221/** Number of errors (incremented by error handle callback). */
     222static uint32_t volatile g_cX11Errors;
     223/** The X11 display. */
     224static Display *g_pX11Display = NULL;
     225/** The X11 dummy window.   */
     226static Window   g_hX11Window = 0;
     227/** TARGETS */
     228static Atom     g_uX11AtomTargets;
     229/** MULTIPLE */
     230static Atom     g_uX11AtomMultiple;
     231
     232#endif
     233
     234
     235/**
     236 * Gets a format descriptor, complaining if invalid format.
    191237 *
    192238 * @returns Pointer to the descriptor if found, NULL + msg if not.
     
    196242{
    197243    for (size_t i = 0; i < RT_ELEMENTS(g_aFormats); i++)
    198         if (strcmp(pszFormat, g_aFormats[i].pszName))
     244        if (strcmp(pszFormat, g_aFormats[i].pszName) == 0)
     245        {
     246#if defined(RT_OS_DARWIN)
     247            /** @todo   */
     248
     249#elif defined(RT_OS_OS2)
     250            if (g_aFormats[i].pszFormat && g_aFormats[i].fFormat == 0)
     251            {
     252                g_aFormats[i].fFormat = WinAddAtom(WinQuerySystemAtomTable(), g_aFormats[i].pszFormat);
     253                if (g_aFormats[i].fFormat == 0)
     254                    RTMsgError("WinAddAtom(,%s) failed: %u (%#x)", g_aFormats[i].pszFormat, WinGetLastError(), WinGetLastError());
     255            }
     256
     257#elif defined(RT_OS_WINDOWS)
     258            if (g_aFormats[i].pwszFormat && g_aFormats[i].fFormat == 0)
     259            {
     260                g_aFormats[i].fFormat = RegisterClipboardFormatW(pFmtDesc->pwszFormat);
     261                if (g_aFormats[i].fFormat == 0)
     262                    RTMsgError("RegisterClipboardFormatW(%ls) failed: %u (%#x)",
     263                               g_aFormats[i].pwszFormat, GetLastError(), GetLastError());
     264            }
     265#elif defined(CU_X11)
     266            if (g_aFormats[i].pszAtomName && g_aFormats[i].uAtom == 0)
     267                g_aFormats[i].uAtom = XInternAtom(g_pX11Display, g_aFormats[i].pszAtomName, False);
     268#endif
    199269            return &g_aFormats[i];
    200     RTMsgError("Unknown format '%s'", pszFormat);
    201     return NULL;
    202 }
    203 
    204 #ifdef RT_OS_WINDOWS
     270        }
     271
     272    /*
     273     * Try register the format.
     274     */
     275    static CLIPUTILFORMAT AdHoc;
     276    AdHoc.pszName     = pszFormat;
     277    AdHoc.pszDesc     = pszFormat;
     278    AdHoc.fFlags      = CLIPUTILFORMAT_F_AD_HOC;
     279#ifdef RT_OS_DARWIN
     280/** @todo   */
     281
     282#elif defined(RT_OS_OS2)
     283    AdHoc.pszFormat   = pszDesc;
     284    AdHoc.fFormat     = WinAddAtom(WinQuerySystemAtomTable(), pwszDesc);
     285    if (AdHoc.fFormat == 0)
     286    {
     287        RTMsgError("Invalid format '%s' (%u (%#x))", pszFormat, WinGetLastError(), WinGetLastError());
     288        return NULL;
     289    }
     290
     291#elif defined(RT_OS_WINDOWS)
     292    AdHoc.pwszFormat  = NULL;
     293    AdHoc.fFormat     = RegisterClipboardFormatA(pszFormat);
     294    if (AdHoc.fFormat == 0)
     295    {
     296        RTMsgError("RegisterClipboardFormatA(%s) failed: %u (%#x)", pszFormat, GetLastError(), GetLastError());
     297        return NULL;
     298    }
     299
     300#else
     301    AdHoc.pszAtomName = pszFormat;
     302    AdHoc.uAtom       = XInternAtom(g_pX11Display, pszFormat, False);
     303    if (AdHoc.uAtom == None)
     304    {
     305        RTMsgError("Invalid format '%s' or out of memory for X11 atoms", pszFormat);
     306        return NULL;
     307    }
     308
     309#endif
     310    return &AdHoc;
     311}
     312
     313
     314#ifdef RT_OS_DARWIN
     315
     316/** @todo   */
     317
     318
     319#elif defined(RT_OS_OS2)
     320
     321/**
     322 * Initialize the OS/2 bits.
     323 */
     324static RTEXITCODE CuOs2Init(void)
     325{
     326    g_hOs2Hab = WinInitialize(0);
     327    if (g_hOs2Hab == NULLHANDLE)
     328        return RTMsgErrorExitFailure("WinInitialize failed: %u", WinGetLastError());
     329
     330    g_hOs2MsgQueue = WinCreateMsgQueue(g_hOs2Hab, 10);
     331    if (g_hOs2MsgQueue == NULLHANDLE)
     332        return RTMsgErrorExitFailure("WinCreateMsgQueue failed: %u", WinGetLastError());
     333    return RTEXITCODE_SUCCESS;
     334}
     335
     336
     337/**
     338 * Terminates the OS/2 bits.
     339 */
     340static RTEXITCODE CuOs2Term(void)
     341{
     342    if (g_fOs2OpenedClipboard)
     343    {
     344        if (!WinCloseClipbrd(g_hOs2Hab))
     345            return RTMsgErrorExitFailure("WinCloseClipbrd failed: %u", WinGetLastError());
     346        g_fOs2OpenedClipboard = false;
     347    }
     348
     349    WinDestroyMsgQueue(g_hOs2Hab, g_hOs2MsgQueue);
     350    g_hOs2MsgQueue = NULLHANDLE;
     351
     352    WinTerminate(g_hOs2Hab);
     353    g_hOs2Hab = NULLHANDLE;
     354
     355    return RTEXITCODE_SUCCESS;
     356}
     357
     358
     359#elif defined(RT_OS_WINDOWS)
     360
     361/**
     362 * Terminates the Windows bits.
     363 */
     364static RTEXITCODE CuWinTerm(void)
     365{
     366    if (g_fOpenedClipboard)
     367    {
     368        if (!CloseClipboard())
     369            return RTMsgErrorExitFailure("CloseClipboard failed: %u (%#x)", GetLastError(), GetLastError());
     370        g_fOpenedClipboard = false;
     371    }
     372    return RTEXITCODE_SUCCESS;
     373}
     374
    205375
    206376/**
     
    220390
    221391
    222 /**
    223  * Wrapper that automatically registers non-standard formats.
    224  */
    225 static UINT FormatDescToWindows(PCCLIPUTILFORMAT pFmtDesc)
    226 {
    227     if (pFmtDesc->fFormat)
    228         return pFmtDesc->fFormat;
    229     Assert(pFmtDesc->pwszFormat);
    230     UINT fFormat = RegisterClipboardFormatW(pFmtDesc->pwszFormat);
    231     if (fFormat == 0)
    232         RTMsgError("RegisterClipboardFormatW(%ls) failed: %u (%#x)", pFmtDesc->pwszFormat, GetLastError(), GetLastError());
    233     return fFormat;
    234 }
    235 
    236 #endif /* RT_OS_WINDOWS */
    237 
     392#else /* X11: */
     393
     394/**
     395 * Error handler callback.
     396 */
     397static int CuX11ErrorCallback(Display *pX11Display, XErrorEvent *pErrEvt)
     398{
     399    g_cX11Errors++;
     400    char szErr[2048];
     401    XGetErrorText(pX11Display, pErrEvt->error_code, szErr, sizeof(szErr));
     402    RTMsgError("An X Window protocol error occurred: %s\n"
     403               "  Request code: %u\n"
     404               "  Minor code:   %u\n"
     405               "  Serial number of the failed request: %u\n",
     406               szErr, pErrEvt->request_code, pErrEvt->minor_code, pErrEvt->serial);
     407    return 0;
     408}
     409
     410
     411/**
     412 * Initialize the X11 bits.
     413 */
     414static RTEXITCODE CuX11Init(void)
     415{
     416    /*
     417     * Open the X11 display and create a little dummy window.
     418     */
     419    XSetErrorHandler(CuX11ErrorCallback);
     420    g_pX11Display = XOpenDisplay(NULL);
     421    if (!g_pX11Display)
     422        return RTMsgErrorExitFailure("XOpenDisplay failed");
     423
     424    int const iDefaultScreen = DefaultScreen(g_pX11Display);
     425    g_hX11Window = XCreateSimpleWindow(g_pX11Display,
     426                                       RootWindow(g_pX11Display, iDefaultScreen),
     427                                       0 /*x*/, 0 /*y*/,
     428                                       1 /*cx*/, 1 /*cy*/,
     429                                       0 /*cPxlBorder*/,
     430                                       BlackPixel(g_pX11Display, iDefaultScreen) /*Border*/,
     431                                       WhitePixel(g_pX11Display, iDefaultScreen) /*Background*/);
     432
     433    /*
     434     * Resolve any unknown atom values we might need later.
     435     */
     436    for (size_t i = 0; i < RT_ELEMENTS(g_aTargets); i++)
     437        if (g_aTargets[i].pszAtomName)
     438        {
     439            g_aTargets[i].uAtom = XInternAtom(g_pX11Display, g_aTargets[i].pszAtomName, False);
     440            if (g_uVerbosity > 2)
     441                RTPrintf("target %s atom=%#x\n", g_aTargets[i].pszName, g_aTargets[i].uAtom);
     442        }
     443
     444    g_uX11AtomTargets = XInternAtom(g_pX11Display, "TARGETS", False);
     445    g_uX11AtomMultiple = XInternAtom(g_pX11Display, "MULTIPLE", False);
     446
     447    return RTEXITCODE_SUCCESS;
     448}
     449
     450#endif /* X11 */
    238451
    239452
     
    282495                }
    283496                if (pszName)
    284                     RTPrintf("#%u: %#06x - %s\n", idx, fFormat, pszName);
     497                    RTPrintf("#%02u: %#06x - %s\n", idx, fFormat, pszName);
    285498                else
    286                     RTPrintf("#%u: %#06x\n", idx, fFormat);
     499                    RTPrintf("#%02u: %#06x\n", idx, fFormat);
    287500            }
    288501
     
    293506    }
    294507    return rcExit;
     508
     509#elif defined(CU_X11)
     510
     511    Atom uAtomDst = g_uX11AtomTargets;
     512    int rc = XConvertSelection(g_pX11Display, g_pTarget->uAtom, g_uX11AtomTargets, uAtomDst, g_hX11Window, CurrentTime);
     513    if (g_uVerbosity > 1)
     514        RTPrintf("XConvertSelection -> %d\n", rc);
     515
     516    for (;;)
     517    {
     518        XEvent Evt = {0};
     519        rc = XNextEvent(g_pX11Display, &Evt);
     520        if (Evt.type == SelectionNotify)
     521        {
     522            if (g_uVerbosity > 1)
     523                RTPrintf("XNextEvent -> %d; type=SelectionNotify\n", rc);
     524            if (Evt.xselection.selection == g_pTarget->uAtom)
     525            {
     526                if (Evt.xselection.property == None)
     527                    return RTMsgErrorExitFailure("XConvertSelection(,%s,TARGETS,) failed", g_pTarget->pszName);
     528
     529                Atom            uAtomRetType = 0;
     530                int             iActualFmt   = 0;
     531                unsigned long   cbLeftToRead = 0;
     532                unsigned long   cItems       = 0;
     533                unsigned char  *pbData       = NULL;
     534                rc = XGetWindowProperty(g_pX11Display, g_hX11Window, uAtomDst,
     535                                        0 /*offset*/, sizeof(Atom) * 4096 /* should be enough */, True /*fDelete*/, XA_ATOM,
     536                                        &uAtomRetType, &iActualFmt, &cItems, &cbLeftToRead, &pbData);
     537                if (g_uVerbosity > 1)
     538                    RTPrintf("XConvertSelection -> %d; uAtomRetType=%u iActualFmt=%d cItems=%lu cbLeftToRead=%lu pbData=%p\n",
     539                             rc, uAtomRetType, iActualFmt, cItems, cbLeftToRead, pbData);
     540                if (pbData && cItems > 0)
     541                {
     542                    Atom const *paTargets = (Atom const *)pbData;
     543                    for (unsigned long i = 0; i < cItems; i++)
     544                    {
     545                        const char *pszName = XGetAtomName(g_pX11Display, paTargets[i]);
     546                        if (pszName)
     547                            RTPrintf("#%02u: %#06x - %s\n", i, paTargets[i], pszName);
     548                        else
     549                            RTPrintf("#%02u: %#06x\n", i, paTargets[i]);
     550                    }
     551                }
     552                else
     553                    RTMsgInfo("Empty");
     554                if (pbData)
     555                    XFree(pbData);
     556                return RTEXITCODE_SUCCESS;
     557            }
     558        }
     559        else if (g_uVerbosity > 1)
     560            RTPrintf("XNextEvent -> %d; type=%d\n", rc, Evt.type);
     561    }
    295562
    296563#else
     
    313580    *ppvData = NULL;
    314581    *pcbData = 0;
     582
    315583#ifdef RT_OS_WINDOWS
    316584    RTEXITCODE rcExit = WinOpenClipboardIfNecessary();
    317585    if (rcExit == RTEXITCODE_SUCCESS)
    318586    {
    319         HANDLE hData = GetClipboardData(FormatDescToWindows(pFmtDesc));
     587        HANDLE hData = GetClipboardData(pFmtDesc->fFormat);
    320588        if (hData != NULL)
    321589        {
     
    362630    return rcExit;
    363631
     632#elif defined(CU_X11)
     633
     634    /* Request the data: */
     635    Atom const uAtomDst = pFmtDesc->uAtom;
     636    int rc = XConvertSelection(g_pX11Display, g_pTarget->uAtom, pFmtDesc->uAtom, uAtomDst, g_hX11Window, CurrentTime);
     637    if (g_uVerbosity > 1)
     638        RTPrintf("XConvertSelection -> %d\n", rc);
     639
     640    /* Wait for the reply: */
     641    for (;;)
     642    {
     643        XEvent Evt = {0};
     644        rc = XNextEvent(g_pX11Display, &Evt);
     645        if (Evt.type == SelectionNotify)
     646        {
     647            if (g_uVerbosity > 1)
     648                RTPrintf("XNextEvent -> %d; type=SelectionNotify\n", rc);
     649            if (Evt.xselection.selection == g_pTarget->uAtom)
     650            {
     651                if (Evt.xselection.property == None)
     652                    return RTMsgErrorExitFailure("XConvertSelection(,%s,%s,) failed", g_pTarget->pszName, pFmtDesc->pszName);
     653
     654                /*
     655                 * Retrieve the data.
     656                 */
     657                Atom            uAtomRetType   = 0;
     658                int             cBitsActualFmt = 0;
     659                unsigned long   cbLeftToRead   = 0;
     660                unsigned long   cItems         = 0;
     661                unsigned char  *pbData         = NULL;
     662                rc = XGetWindowProperty(g_pX11Display, g_hX11Window, uAtomDst,
     663                                        0 /*offset*/, _64M, False/*fDelete*/, AnyPropertyType,
     664                                        &uAtomRetType, &cBitsActualFmt, &cItems, &cbLeftToRead, &pbData);
     665                if (g_uVerbosity > 1)
     666                    RTPrintf("XConvertSelection -> %d; uAtomRetType=%u cBitsActualFmt=%d cItems=%lu cbLeftToRead=%lu pbData=%p\n",
     667                             rc, uAtomRetType, cBitsActualFmt, cItems, cbLeftToRead, pbData);
     668                RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     669                if (pbData && cItems > 0)
     670                {
     671                    *pcbData = cItems * (cBitsActualFmt / 8);
     672                    *ppvData = RTMemDup(pbData, *pcbData);
     673                    if (!*ppvData)
     674                        rcExit = RTMsgErrorExitFailure("Out of memory allocating %#zx bytes.", *pcbData);
     675                }
     676                if (pbData)
     677                    XFree(pbData);
     678                XDeleteProperty(g_pX11Display, g_hX11Window, uAtomDst);
     679                return rcExit;
     680            }
     681        }
     682        else if (g_uVerbosity > 1)
     683            RTPrintf("XNextEvent -> %d; type=%d\n", rc, Evt.type);
     684    }
     685
    364686#else
    365687    RT_NOREF(pFmtDesc);
     
    422744            if (rcExit == RTEXITCODE_SUCCESS)
    423745            {
    424                 if (!SetClipboardData(FormatDescToWindows(pFmtDesc), hDstData))
     746                if (!SetClipboardData(pFmtDesc->fFormat, hDstData))
    425747                {
    426748                    rcExit = RTMsgErrorExitFailure("SetClipboardData(%s) failed: %u (%#x)\n",
     
    623945    if (rcExit == RTEXITCODE_SUCCESS)
    624946    {
    625         if (IsClipboardFormatAvailable(FormatDescToWindows(pFmtDesc)))
     947        if (IsClipboardFormatAvailable(pFmtDesc->fFormat))
    626948            rcExit = RTMsgErrorExitFailure("Format '%s' is present");
    627949    }
     
    6861008            case 'z':   pszHelp = "Zaps the clipboard content."; break;
    6871009#ifdef MULTI_TARGET_CLIPBOARD
    688             case 't':   pszHelp = "Selects the target clipboard." break;
     1010            case 't':   pszHelp = "Selects the target clipboard."; break;
    6891011#endif
    6901012            case 'v':   pszHelp = "More verbose execution."; break;
     
    7301052
    7311053    /*
     1054     * Host specific init.
     1055     */
     1056#ifdef RT_OS_DARWIN
     1057    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1058#elif defined(RT_OS_OS2)
     1059    RTEXITCODE rcExit = CuOs2Init();
     1060#elif defined(RT_OS_WINDOWS)
     1061    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1062#else
     1063    RTEXITCODE rcExit = CuX11Init();
     1064#endif
     1065    if (rcExit != RTEXITCODE_SUCCESS)
     1066        return rcExit;
     1067
     1068    /*
    7321069     * Process options (in order).
    7331070     */
    734     RTEXITCODE    rcExit = RTEXITCODE_SUCCESS;
    7351071    RTGETOPTUNION ValueUnion;
    7361072    RTGETOPTSTATE GetState;
     
    7641100                        rcExit2 = ClipboardContentToFile(pFmtDesc, ValueUnion.psz);
    7651101                    else
    766                         return RTMsgError("No filename given with --get-file");
     1102                        return RTMsgErrorExitFailure("No filename given with --get-file");
    7671103                }
    7681104                else
     
    7801116                        rcExit2 = PutStringOnClipboard(pFmtDesc, ValueUnion.psz);
    7811117                    else
    782                         return RTMsgError("No data string given with --put");
     1118                        return RTMsgErrorExitFailure("No data string given with --put");
    7831119                }
    7841120                else
     
    7961132                        rcExit2 = PutFileOnClipboard(pFmtDesc, ValueUnion.psz);
    7971133                    else
    798                         return RTMsgError("No filename given with --put-file");
     1134                        return RTMsgErrorExitFailure("No filename given with --put-file");
    7991135                }
    8001136                else
     
    8121148                        rcExit2 = CheckStringAgainstClipboard(pFmtDesc, ValueUnion.psz);
    8131149                    else
    814                         return RTMsgError("No data string given with --check");
     1150                        return RTMsgErrorExitFailure("No data string given with --check");
    8151151                }
    8161152                else
     
    8281164                        rcExit2 = CheckFileAgainstClipboard(pFmtDesc, ValueUnion.psz);
    8291165                    else
    830                         return RTMsgError("No filename given with --check-file");
     1166                        return RTMsgErrorExitFailure("No filename given with --check-file");
    8311167                }
    8321168                else
     
    8501186                break;
    8511187
     1188#ifdef MULTI_TARGET_CLIPBOARD
     1189            case 't':
     1190            {
     1191                CLIPUTILTARGET *pNewTarget = NULL;
     1192                for (size_t i = 0; i < RT_ELEMENTS(g_aTargets); i++)
     1193                    if (strcmp(ValueUnion.psz, g_aTargets[i].pszName) == 0)
     1194                    {
     1195                        pNewTarget = &g_aTargets[i];
     1196                        break;
     1197                    }
     1198                if (!pNewTarget)
     1199                    return RTMsgErrorExitFailure("Unknown target '%s'", ValueUnion.psz);
     1200                if (pNewTarget != g_pTarget && g_uVerbosity > 0)
     1201                    RTMsgInfo("Switching from '%s' to '%s'\n", g_pTarget->pszName, pNewTarget->pszName);
     1202                g_pTarget = pNewTarget;
     1203                break;
     1204            }
     1205#endif
     1206
    8521207            case 'q':
    8531208                g_uVerbosity = 0;
     
    8811236     * Host specific cleanup.
    8821237     */
    883 #ifdef RT_OS_WINDOWS
    884     if (g_fOpenedClipboard)
    885     {
    886         if (!CloseClipboard())
    887             rcExit = RTMsgErrorExitFailure("CloseClipboard failed: %u (%#x)", GetLastError(), GetLastError());
    888     }
    889 #endif
     1238#if defined(RT_OS_OS2)
     1239    RTEXITCODE rcExit2 = CuOs2Term();
     1240#elif defined(RT_OS_WINDOWS)
     1241    RTEXITCODE rcExit2 = CuWinTerm();
     1242#else
     1243    RTEXITCODE rcExit2 = RTEXITCODE_SUCCESS;
     1244#endif
     1245    if (rcExit2 != RTEXITCODE_SUCCESS && rcExit != RTEXITCODE_SUCCESS)
     1246        rcExit = rcExit2;
    8901247
    8911248    return rcExit;
  • trunk/src/VBox/ValidationKit/utils/clipboard/Makefile.kmk

    r92025 r92158  
    3434ClipUtil_TEMPLATE = VBoxValidationKitR3
    3535ClipUtil_SOURCES  = ClipUtil.cpp
     36ifn1of ($(KBUILD_TARGET), darwin os2 windows)
     37ClipUtil_LIBPATH  = $(VBOX_LIBPATH_X11)
     38ClipUtil_LIBS     = X11 Xmu
     39endif
    3640
    3741$(evalcall def_vbox_validationkit_process_python_sources)
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette