From 543ca83524a7e7aa3c7d87227c2ac8dbff2033ff Mon Sep 17 00:00:00 2001
From: Antonio Ospite <ao2@ao2.it>
Date: Mon, 19 Jun 2017 14:03:41 +0200
Subject: [PATCH] Initial import

---
 .gitignore         |  1 +
 Makefile           | 41 +++++++++++++++++++++++++++++++++++++++++
 README.txt         | 42 ++++++++++++++++++++++++++++++++++++++++++
 dump_selections.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++
 xowner.c           | 27 +++++++++++++++++++++++++++
 5 files changed, 155 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
 create mode 100644 README.txt
 create mode 100755 dump_selections.sh
 create mode 100644 xowner.c

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07f01a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+xowner
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d6ea625
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+CFLAGS ?= -std=c99 -pedantic -pedantic-errors -Wall -g3 -O2 -D_ANSI_SOURCE_
+CFLAGS += -fno-common \
+	  -Wall \
+	  -Wdeclaration-after-statement \
+	  -Wextra \
+	  -Wformat=2 \
+	  -Winit-self \
+	  -Winline \
+	  -Wpacked \
+	  -Wp,-D_FORTIFY_SOURCE=2 \
+	  -Wpointer-arith \
+	  -Wlarger-than-65500 \
+	  -Wmissing-declarations \
+	  -Wmissing-format-attribute \
+	  -Wmissing-noreturn \
+	  -Wmissing-prototypes \
+	  -Wnested-externs \
+	  -Wold-style-definition \
+	  -Wredundant-decls \
+	  -Wsign-compare \
+	  -Wstrict-aliasing=2 \
+	  -Wstrict-prototypes \
+	  -Wundef \
+	  -Wunreachable-code \
+	  -Wunused-variable \
+	  -Wwrite-strings
+
+ifneq ($(CC),clang)
+  CFLAGS += -Wunsafe-loop-optimizations
+endif
+
+EXECUTABLE := xowner
+LDLIBS := -lX11
+
+$(EXECUTABLE):
+
+clean:
+	rm -f *~ *.o $(EXECUTABLE)
+
+test: $(EXECUTABLE)
+	valgrind --leak-check=full --show-reachable=yes ./$(EXECUTABLE) PRIMARY
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..9dad622
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,42 @@
+Some simple tools to analyze X selection buffers to understand what is going
+on when text is selected with the mouse in X11.
+
+
+BACK STORY
+==========
+
+When vim is compiled with the +clipboad and +xterm_clipboard functionalities,
+and setmouse=a is set, using vim in combination with xterm allows this
+workflow:
+
+ 1. Select something with the mouse;
+ 2. exit vim;
+ 3. paste the previously selected text with the middle mouse click.
+
+Moving from xterm to gnome-terminal this workflow is not possible by default.
+
+It turns out this is not a missing feature of vte or gtk, but rather some
+extra functionality offered only by the combination of vim and xterm.
+
+Vim copies to the CUT_BUFFER0 selection when it exits and xterm is able to
+paste from CUT_BUFFER0 when it receives a middle click.
+
+To make the workflow from above possible again it is possible to have vim
+preserve the PRIMARY selection when it exits with a command like the following
+in ~/.vimrc:
+
+  autocmd VimLeave * call system("xsel -ip", getreg('*'))
+
+All the details of how the issue have been debugged can be found at
+https://bugzilla.gnome.org/show_bug.cgi?id=783828
+
+
+REFERENCES
+==========
+
+https://www.jwz.org/doc/x-cut-and-paste.html
+https://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html
+https://stackoverflow.com/questions/6453595/prevent-vim-from-clearing-the-clipboard-on-exit
+https://vi.stackexchange.com/questions/3769/can-vim-add-to-the-x11-clipboard-or-primary-buffers-without-an-external-utility#comment5354_3769
+https://groups.google.com/forum/#!topic/vim_dev/nlyA7AN9mfQ
+https://groups.google.com/forum/#!topic/vim_use/NtprNch2ZkQ
diff --git a/dump_selections.sh b/dump_selections.sh
new file mode 100755
index 0000000..1f9da7b
--- /dev/null
+++ b/dump_selections.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+[ -x ./xowner ] || make
+
+get_owner() {
+  echo -n "$1"
+  OWNER=$(./xowner $1)
+  if [ $OWNER != "0x0" ];
+  then
+    xwininfo -id $OWNER > /dev/null 2>&1;
+    if [ $? -eq 0 ];
+    then
+      OWNER_NAME=$(xprop -id $OWNER WM_NAME | cut -d ' ' -f 3-)
+      if [ -z "$OWNER_NAME" ];
+      then
+        OWNER_NAME="$OWNER"
+      fi
+      echo -n " owned by $OWNER_NAME"
+    fi
+  fi
+
+  echo ":"
+}
+
+
+get_owner "PRIMARY"
+xclip -out -selection primary 2> /dev/null
+echo
+echo
+
+get_owner "SECONDARY"
+xclip -out -selection secondary 2> /dev/null
+echo
+echo
+
+get_owner "CLIPBOARD"
+xclip -out -selection clipboard 2> /dev/null
+echo
+echo
+
+get_owner "CUT_BUFFER0"
+xcb -p 0
+echo
+echo
diff --git a/xowner.c b/xowner.c
new file mode 100644
index 0000000..5cbfefd
--- /dev/null
+++ b/xowner.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+
+int main(int argc, char *argv[])
+{
+	Display *dpy;
+	Window owner;
+	Atom sel;
+
+	if (argc < 2) {
+		fprintf(stderr, "usage: xowner <selection>\n");
+		return 1;
+	}
+
+	dpy = XOpenDisplay(NULL);
+	if (!dpy) {
+		fprintf(stderr, "Could not open X display\n");
+		return 1;
+	}
+
+	sel = XInternAtom(dpy, argv[1], False);
+	owner = XGetSelectionOwner(dpy, sel);
+	printf("0x%lX\n", owner);
+
+	XCloseDisplay(dpy);
+	return 0;
+}
-- 
2.1.4