From b022f0dbd914256efb1f22fa11ad8338216609db Mon Sep 17 00:00:00 2001 From: hujianwei Date: Sat, 12 Nov 2022 08:07:43 +0000 Subject: [PATCH] Fix handling of MULTIPLE selections and add test * select.c (SignalConversionPerformed): Improve diagnostic messages. (ConvertSelectionMultiple): Use correct atoms. (HandleSelectionRequest): Allow selection requests with target MULTIPLE. * tests/Imakefile (SRCS12, OBJS12): Add select_helper_multiple.c and .o. (PROGRAMS): Add select_helper_multiple. (select_helper_multiple): New program. * tests/select_helper.c (main): Fix typo. * tests/select_test.c (verify_sample_text_multiple): New function. (test_single_step): Call it. * tests/svnignore.txt: Add select_helper_multiple. --- select.c | 16 ++++----- tests/Imakefile | 7 ++-- tests/select_helper.c | 3 +- tests/select_test.c | 78 +++++++++++++++++++++++++++++++++++++++++++ tests/svnignore.txt | 1 + 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/select.c b/select.c index 37e8b4b..4901277 100644 --- a/select.c +++ b/select.c @@ -23,9 +23,6 @@ along with 12to11. If not, see . */ #include "compositor.h" -/* Caveat: the MULTIPLE target implementation is completely untested - and probably doesn't work. */ - typedef struct _PropertyAtom PropertyAtom; typedef struct _SelectInputData SelectInputData; typedef struct _SelectionOwnerInfo SelectionOwnerInfo; @@ -808,8 +805,8 @@ SignalConversionPerformed (WriteTransfer *transfer) are still pending. If there are no more pending conversions, send the SelectionNotify event and return. */ - DebugPrint ("Conversion complete; %d conversions are still pending\n", - transfer->record->pending); + DebugPrint ("Conversion complete; %d conversion(s) are still pending\n", + transfer->record->pending - 1); if (!(--transfer->record->pending)) { @@ -1327,8 +1324,8 @@ ConvertSelectionMultiple (SelectionOwnerInfo *info, XEvent *event, transfer->last = &write_transfers; transfer->requestor = event->xselectionrequest.requestor; transfer->selection = event->xselectionrequest.selection; - transfer->target = event->xselectionrequest.target; - transfer->property = atoms[1]; + transfer->target = atoms[i + 0]; + transfer->property = atoms[i + 1]; transfer->time = event->xselectionrequest.time; transfer->buffer = XLMalloc (quantum); transfer->size = quantum; @@ -1425,7 +1422,10 @@ HandleSelectionRequest (XEvent *event) do anyway. */ || (event->xselectionrequest.time != CurrentTime && TimeIs (event->xselectionrequest.time, Earlier, info->time)) - || !CanConvertTarget (info, event->xselectionrequest.target)) + || (!CanConvertTarget (info, event->xselectionrequest.target) + /* CanConvertTarget itself does not understand MULTIPLE, + because it itself is called while handling MULTIPLE. */ + && event->xselectionrequest.target != MULTIPLE)) { DebugPrint ("Couldn't convert selection due to simple reason\n"); diff --git a/tests/Imakefile b/tests/Imakefile index 432b74c..fb4ad0d 100644 --- a/tests/Imakefile +++ b/tests/Imakefile @@ -50,7 +50,9 @@ ScannerTarget(linux-dmabuf-unstable-v1) OBJS10 = $(COMMONSRCS) select_test.o SRCS11 = select_helper.c OBJS11 = select_helper.o - PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper + SRCS12 = select_helper_multiple.c + OBJS12 = select_helper_multiple.o + PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple /* Make all objects depend on HEADER. */ $(OBJS1): $(HEADER) @@ -69,10 +71,11 @@ NormalProgramTarget(seat_test,$(OBJS8),NullParameter,$(LOCAL_LIBRARIES),NullPara NormalProgramTarget(dmabuf_test,$(OBJS9),NullParameter,$(LOCAL_LIBRARIES) $(GBM) $(DRM),NullParameter); NormalProgramTarget(select_test,$(OBJS10),NullParameter,$(LOCAL_LIBRARIES) ThreadsLibraries,NullParameter); NormalProgramTarget(select_helper,$(OBJS11),NullParameter,$(XLIB),NullParameter); +NormalProgramTarget(select_helper_multiple,$(OBJS12),NullParameter,$(XLIB),NullParameter); DependTarget3($(SRCS1),$(SRCS2),$(SRCS3)) DependTarget3($(SRCS4),$(SRCS5),$(SRCS6)) DependTarget3($(SRCS7),$(SRCS8),$(SRCS9)) -DependTarget3($(SRCS10),$(SRCS11),NullParameter) +DependTarget3($(SRCS10),$(SRCS11),$(SRCS12)) all:: $(PROGRAMS) diff --git a/tests/select_helper.c b/tests/select_helper.c index a2cdf70..e5c5498 100644 --- a/tests/select_helper.c +++ b/tests/select_helper.c @@ -31,7 +31,6 @@ along with 12to11. If not, see . */ There must be three arguments: the name of the display, the timestamp at which the selection was acquired, and the target. */ - /* The display connected to. */ static Display *display; @@ -130,7 +129,7 @@ main (int argc, char **argv) atom_names[0] = argv[3]; atom_names[1] = (char *) "CLIPBOARD"; - atom_names[2] = (char *) "CLIPBOARD"; + atom_names[2] = (char *) "INCR"; XInternAtoms (display, atom_names, 3, False, atoms); target_atom = atoms[0]; CLIPBOARD = atoms[1]; diff --git a/tests/select_test.c b/tests/select_test.c index 626c9b8..2dca648 100644 --- a/tests/select_test.c +++ b/tests/select_test.c @@ -246,6 +246,79 @@ verify_sample_text (Time time) close (pipefds[1]); } +static void +verify_sample_text_multiple (Time time) +{ + int pipefds[2], wstatus; + pid_t pid; + char *display_string; + char time_buffer[45], buffer[sizeof SAMPLE_TEXT]; + ssize_t bytes_read; + const char *sample_text_buffer; + + /* Run select_helper with the specified timestamp. Wait until + handle_data_source_send is called, and then begin reading from + the pipe. */ + + if (pipe (pipefds) < 0) + die ("pipe"); + + display_string = DisplayString (display->x_display); + time = sprintf (time_buffer, "%lu", time); + pid = fork (); + + if (pid == -1) + die ("fork"); + else if (!pid) + { + close (pipefds[0]); + + if (!dup2 (pipefds[1], 1)) + exit (1); + + execlp ("./select_helper_multiple", "./select_helper", + display_string, time_buffer, "STRING", "UTF8_STRING", + NULL); + exit (1); + } + + send_called = false; + + while (!send_called) + { + if (wl_display_dispatch (display->display) == -1) + die ("wl_display_dispatch"); + } + + /* Now, start reading from the pipe and comparing the contents. */ + sample_text_buffer = SAMPLE_TEXT; + bytes_read = read (pipefds[0], buffer, sizeof SAMPLE_TEXT - 1); + + if (bytes_read != sizeof SAMPLE_TEXT - 1) + report_test_failure ("wanted %zu bytes, but got %zd", + sizeof SAMPLE_TEXT - 1, bytes_read); + + /* Now compare the text. */ + if (memcmp (buffer, sample_text_buffer, bytes_read)) + report_test_failure ("read text differs from sample text!"); + + /* Compare the text again for the second target. */ + bytes_read = read (pipefds[0], buffer, sizeof SAMPLE_TEXT - 1); + + if (bytes_read != sizeof SAMPLE_TEXT - 1) + report_test_failure ("wanted %zu bytes, but got %zd", + sizeof SAMPLE_TEXT - 1, bytes_read); + + waitpid (pid, &wstatus, 0); + + if (WEXITSTATUS (wstatus)) + report_test_failure ("child exited with failure: %d", + WEXITSTATUS (wstatus)); + + close (pipefds[0]); + close (pipefds[1]); +} + static void @@ -271,7 +344,12 @@ test_single_step (enum test_kind kind) wl_display_roundtrip (display->display); /* Now, verify the selection contents. */ + test_log ("verifying sample text normally"); verify_sample_text (time); + + /* And verify the selection contents for MULTIPLE. */ + test_log ("verifying sample text via MULTIPLE"); + verify_sample_text_multiple (time); break; } diff --git a/tests/svnignore.txt b/tests/svnignore.txt index 38fdf26..246cf29 100644 --- a/tests/svnignore.txt +++ b/tests/svnignore.txt @@ -11,6 +11,7 @@ seat_test dmabuf_test select_test select_helper +select_helper_multiple imgview reject.dump Makefile