Command-line option to choose an X selection.
authorSimon Tatham <anakin@pobox.com>
Wed, 18 Mar 2020 20:59:12 +0000 (20:59 +0000)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
I personally find it more convenient to have pasted data written to
the X11 PRIMARY selection, so that I can paste it with a fast middle-
button click, than to write to CLIPBOARD which typically needs a key
sequence or menu action.

This commit adds a command-line option to let me express that
preference: now I can say "/clipboard:use-selection:PRIMARY" on the
command line, which not only enables clipboard transfer but also says
which X selection I want it to talk to. The previous options
"+clipboard" and "-clipboard" are also still supported.

(cherry picked from commit 64948b96c4c4640078ce563b165a907251fd6f20)

client/X11/xf_cliprdr.c
client/common/cmdline.c
client/common/cmdline.h
include/freerdp/settings.h
libfreerdp/core/settings.c

index 7f178d8..4125d0d 100644 (file)
@@ -1684,6 +1684,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
        int i, n = 0;
        rdpChannels* channels;
        xfClipboard* clipboard;
+       const char* selectionAtom;
 
        if (!(clipboard = (xfClipboard*)calloc(1, sizeof(xfClipboard))))
        {
@@ -1698,11 +1699,14 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
        clipboard->system = ClipboardCreate();
        clipboard->requestedFormatId = -1;
        clipboard->root_window = DefaultRootWindow(xfc->display);
-       clipboard->clipboard_atom = XInternAtom(xfc->display, "CLIPBOARD", FALSE);
+       selectionAtom = "CLIPBOARD";
+       if (xfc->context.settings->XSelectionAtom)
+               selectionAtom = xfc->context.settings->XSelectionAtom;
+       clipboard->clipboard_atom = XInternAtom(xfc->display, selectionAtom, FALSE);
 
        if (clipboard->clipboard_atom == None)
        {
-               WLog_ERR(TAG, "unable to get CLIPBOARD atom");
+               WLog_ERR(TAG, "unable to get %s atom", selectionAtom);
                goto error;
        }
 
index 1684df1..3f786ec 100644 (file)
@@ -2343,7 +2343,36 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
                }
                CommandLineSwitchCase(arg, "clipboard")
                {
-                       settings->RedirectClipboard = enable;
+                       if (arg->Value == BoolValueTrue || arg->Value == BoolValueFalse)
+                       {
+                               settings->RedirectClipboard = (arg->Value == BoolValueTrue);
+                       }
+                       else
+                       {
+                               int rc = 0;
+                               char** p;
+                               size_t count, x;
+                               p = CommandLineParseCommaSeparatedValues(arg->Value, &count);
+                               for (x = 0; (x < count) && (rc == 0); x++)
+                               {
+                                       const char usesel[14] = "use-selection:";
+
+                                       const char* cur = p[x];
+                                       if (_strnicmp(usesel, cur, sizeof(usesel)) == 0)
+                                       {
+                                               const char* val = &cur[sizeof(usesel)];
+                                               if (!copy_value(val, &settings->XSelectionAtom))
+                                                       rc = COMMAND_LINE_ERROR_MEMORY;
+                                               settings->RedirectClipboard = TRUE;
+                                       }
+                                       else
+                                               rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
+                               }
+                               free(p);
+
+                               if (rc)
+                                       return rc;
+                       }
                }
                CommandLineSwitchCase(arg, "shell")
                {
index 3ae8af1..065cfc5 100644 (file)
@@ -102,8 +102,12 @@ static const COMMAND_LINE_ARGUMENT_A args[] = {
          "Client Build Number sent to server (influences smartcard behaviour, see [MS-RDPESC])" },
        { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL,
          "Client Hostname to send to server" },
-       { "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
-         "Redirect clipboard" },
+       { "clipboard", COMMAND_LINE_VALUE_BOOL | COMMAND_LINE_VALUE_OPTIONAL, "[use-selection:<atom>]",
+         BoolValueTrue, NULL, -1, NULL,
+         "Redirect clipboard.                       "
+         " * use-selection:<atom>  ... (X11) Specify which X selection to access. Default is "
+         "CLIPBOARD."
+         " PRIMARY is the X-style middle-click selection." },
        { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "[rfx|nsc|jpeg]", NULL, NULL, -1, NULL,
          "Bitmap codec cache" },
        { "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "compression" },
index 99bc0d2..6bf222d 100644 (file)
@@ -1559,6 +1559,7 @@ struct rdp_settings
                                           default value - currently UNUSED! */
        ALIGN64 char* ActionScript;
        ALIGN64 DWORD Floatbar;
+       ALIGN64 char* XSelectionAtom;
 };
 typedef struct rdp_settings rdpSettings;
 
index d335179..23f5f05 100644 (file)
@@ -594,6 +594,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
        settings_load_hkey_local_machine(settings);
 
        settings->ActionScript = _strdup("~/.config/freerdp/action.sh");
+       settings->XSelectionAtom = NULL;
        settings->SmartcardLogon = FALSE;
        settings->TlsSecLevel = 1;
        settings->OrderSupport = calloc(1, 32);
@@ -640,6 +641,8 @@ static void freerdp_settings_free_internal(rdpSettings* settings)
        /* Extensions */
        free(settings->ActionScript);
        settings->ActionScript = NULL;
+       free(settings->XSelectionAtom);
+       settings->XSelectionAtom = NULL;
 
        /* Free all strings, set other pointers NULL */
        freerdp_settings_free_keys(settings, TRUE);
@@ -967,6 +970,8 @@ static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings, const rdpSe
 
        if (settings->ActionScript)
                _settings->ActionScript = _strdup(settings->ActionScript);
+       if (settings->XSelectionAtom)
+               _settings->XSelectionAtom = _strdup(settings->XSelectionAtom);
        rc = TRUE;
 out_fail:
        return rc;
@@ -1008,6 +1013,7 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
        _settings->StaticChannelArray = NULL;
        _settings->DynamicChannelArray = NULL;
        _settings->ActionScript = NULL;
+       _settings->XSelectionAtom = NULL;
        if (!rc)
                goto out_fail;