From ed6f6f5a93ef265fcaaff410cc330f205715e971 Mon Sep 17 00:00:00 2001 From: Craig Date: Sun, 2 Feb 2020 22:48:23 +0000 Subject: [PATCH] libclipboard --- .devcontainer/Dockerfile | 17 ++- .devcontainer/devcontainer.json | 8 +- Dockerfile | 24 +++- neko.code-workspace | 7 +- server/internal/clip/clip.c | 23 ++++ server/internal/clip/clip.go | 21 ++++ server/internal/clip/clip.h | 5 + server/internal/hid/clipboard/clipboard.go | 124 --------------------- server/internal/websocket/control.go | 4 +- server/internal/websocket/websocket.go | 16 +-- 10 files changed, 103 insertions(+), 146 deletions(-) create mode 100644 server/internal/clip/clip.c create mode 100644 server/internal/clip/clip.go create mode 100644 server/internal/clip/clip.h delete mode 100644 server/internal/hid/clipboard/clipboard.go diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index c5ba239f..2fa781ff 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -4,7 +4,7 @@ FROM debian:stretch-slim # cluster fuck of packages for neko, node, go and gstreamer RUN set -eux; apt-get update; apt-get install -y --no-install-recommends \ autoconf ca-certificates curl netbase wget \ - bzr git mercurial openssh-client subversion procps automake bzip2 dpkg-dev file g++ gcc \ + bzr git mercurial openssh-client subversion procps cmake automake bzip2 dpkg-dev file g++ gcc \ libbz2-dev libc6-dev libcurl4-openssl-dev libdb-dev libevent-dev libffi-dev libgdbm-dev libglib2.0-dev libgmp-dev \ libjpeg-dev libkrb5-dev liblzma-dev libmagickcore-dev libmagickwand-dev libmaxminddb-dev libncurses5-dev libncursesw5-dev \ libpng-dev libpq-dev libreadline-dev libsqlite3-dev libssl-dev libtool libwebp-dev libxml2-dev libxslt-dev libyaml-dev \ @@ -96,6 +96,17 @@ RUN set -eux; \ ENV GOPATH /go ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH +# +# install libclipboard +RUN set -eux; \ + cd /tmp ; \ + git clone https://github.com/jtanx/libclipboard ; \ + cd libclipboard ; \ + cmake -DBUILD_SHARED_LIBS=ON -DLIBCLIPBOARD_FORCE_X11=on -DLIBCLIPBOARD_ADD_SOVERSION=ON --prefix=/usr/local . ; \ + make -j4; \ + make install; \ + rm -rf /tmp/libclipboard + # # install Go tools w/module support RUN set -eux; \ @@ -156,6 +167,10 @@ ARG INSTALL_ZSH="true" ARG COMMON_SCRIPT_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/master/script-library/common-debian.sh" ARG COMMON_SCRIPT_SHA="dev-mode" +# +# Docker Compose version +ARG COMPOSE_VERSION=1.24.0 + # # verify git, common tools / libs installed, add/modify non-root user, optionally install zsh RUN set -eux; \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4662b7b7..285e531b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,19 +7,19 @@ "settings": { "terminal.integrated.shell.linux": "/bin/bash", "go.gopath": "/go" - }, + }, "extensions": [ "ms-vscode.go", "octref.vetur", + "ms-vscode.cpptools", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "ms-vscode-remote.vscode-remote-extensionpack", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", "editorconfig.editorconfig", - "psioniq.psi-header", "gruntfuggly.todo-tree", - "swyphcosmo.spellchecker", - "eamodio.gitlens" + "eamodio.gitlens", + "swyphcosmo.spellchecker" ] } diff --git a/Dockerfile b/Dockerfile index c29eefc3..bdac0adb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ FROM debian:stretch-slim +# # avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive @@ -7,9 +8,27 @@ ARG USERNAME=neko ARG USER_UID=1000 ARG USER_GID=$USER_UID +# +# install libclipboard +RUN set -eux; apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates git cmake pkg-config build-essential libx11-dev ; \ + cd /tmp ; \ + git clone https://github.com/jtanx/libclipboard ; \ + cd libclipboard ; \ + cmake -DBUILD_SHARED_LIBS=ON -DLIBCLIPBOARD_FORCE_X11=on -DLIBCLIPBOARD_ADD_SOVERSION=ON --prefix=/usr/local . ; \ + make -j4; \ + make install; \ + rm -rf /tmp/libclipboard ; \ + # + # clean up + apt-get autoremove -y git cmake pkg-config build-essential libx11-dev; \ + apt-get clean -y; \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/* + +# # install neko dependencies RUN set -eux; apt-get update; \ - apt-get install -y --no-install-recommends wget ca-certificates pulseaudio openbox dbus-x11 xvfb xclip supervisor; \ + apt-get install -y --no-install-recommends wget ca-certificates pulseaudio openbox dbus-x11 xvfb supervisor; \ apt-get install -y --no-install-recommends libxv1 libopus0 libvpx4; \ # # create a non-root user @@ -31,15 +50,16 @@ RUN set -eux; apt-get update; \ chown -R $USERNAME:$USERNAME /home/$USERNAME; \ # # clean up - apt-get autoremove -y; \ apt-get clean -y; \ rm -rf /var/lib/apt/lists/* /var/cache/apt/* +# # add gst to env ENV PATH=/gst/local/bin:$PATH ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH +# # copy gst COPY .build/gst/local /gst/local/ diff --git a/neko.code-workspace b/neko.code-workspace index 5e0bf377..997329c9 100644 --- a/neko.code-workspace +++ b/neko.code-workspace @@ -33,6 +33,7 @@ "remote.containers.defaultExtensions": [ "ms-vscode.go", "octref.vetur", + "ms-vscode.cpptools", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "ms-vscode-remote.vscode-remote-extensionpack", @@ -40,8 +41,8 @@ "ms-azuretools.vscode-docker", "editorconfig.editorconfig", "gruntfuggly.todo-tree", - "swyphcosmo.spellchecker", - "eamodio.gitlens" - ], + "eamodio.gitlens", + "swyphcosmo.spellchecker" + ] } } \ No newline at end of file diff --git a/server/internal/clip/clip.c b/server/internal/clip/clip.c new file mode 100644 index 00000000..a2db5af6 --- /dev/null +++ b/server/internal/clip/clip.c @@ -0,0 +1,23 @@ +#include "clip.h" + +#include +#include + +clipboard_c *CLIPBOARD = NULL; + +clipboard_c *getClipboard(void) { + if (CLIPBOARD == NULL) { + CLIPBOARD = clipboard_new(NULL); + } + return CLIPBOARD; +} + +void set_clipboard(char *src) { + clipboard_c *cb = getClipboard(); + clipboard_set_text_ex(cb, src, strlen(src), 0); +} + +char * get_clipboard() { + clipboard_c *cb = getClipboard(); + return clipboard_text_ex(cb, NULL, 0); +} diff --git a/server/internal/clip/clip.go b/server/internal/clip/clip.go new file mode 100644 index 00000000..5e25a51f --- /dev/null +++ b/server/internal/clip/clip.go @@ -0,0 +1,21 @@ +// NOTE: I have no fucking clue what I'm doing with this, +// it works, but I am positive I'm doing this very wrong... +// should I be freeing these strings? does go cg them? +// pretty sure this *isn't* thread safe either.... /shrug + +package clip + +/* +#cgo linux LDFLAGS: -lclipboard + +#include "clip.h" +*/ +import "C" + +func Read() string { + return C.GoString(C.get_clipboard()) +} + +func Write(data string) { + C.set_clipboard(C.CString(data)) +} diff --git a/server/internal/clip/clip.h b/server/internal/clip/clip.h new file mode 100644 index 00000000..c9936350 --- /dev/null +++ b/server/internal/clip/clip.h @@ -0,0 +1,5 @@ +#include + +clipboard_c *getClipboard(void); +void set_clipboard(char *src); +char * get_clipboard(); diff --git a/server/internal/hid/clipboard/clipboard.go b/server/internal/hid/clipboard/clipboard.go deleted file mode 100644 index 628aeefd..00000000 --- a/server/internal/hid/clipboard/clipboard.go +++ /dev/null @@ -1,124 +0,0 @@ -package clipboard - -import ( - "errors" - "os" - "os/exec" -) - -const ( - xsel = "xsel" - xclip = "xclip" - wlcopy = "wl-copy" - wlpaste = "wl-paste" - termuxClipboardGet = "termux-clipboard-get" - termuxClipboardSet = "termux-clipboard-set" -) - -var ( - Unsupported bool - Primary bool - - pasteCmdArgs []string - copyCmdArgs []string - - xselPasteArgs = []string{xsel, "--output", "--clipboard"} - xselCopyArgs = []string{xsel, "--input", "--clipboard"} - - xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} - xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} - - wlpasteArgs = []string{wlpaste, "--no-newline"} - wlcopyArgs = []string{wlcopy} - - termuxPasteArgs = []string{termuxClipboardGet} - termuxCopyArgs = []string{termuxClipboardSet} - - missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") -) - -func init() { - if os.Getenv("WAYLAND_DISPLAY") != "" { - pasteCmdArgs = wlpasteArgs - copyCmdArgs = wlcopyArgs - - if _, err := exec.LookPath(wlcopy); err == nil { - if _, err := exec.LookPath(wlpaste); err == nil { - return - } - } - } - - pasteCmdArgs = xclipPasteArgs - copyCmdArgs = xclipCopyArgs - - if _, err := exec.LookPath(xclip); err == nil { - return - } - - pasteCmdArgs = xselPasteArgs - copyCmdArgs = xselCopyArgs - - if _, err := exec.LookPath(xsel); err == nil { - return - } - - pasteCmdArgs = termuxPasteArgs - copyCmdArgs = termuxCopyArgs - - if _, err := exec.LookPath(termuxClipboardSet); err == nil { - if _, err := exec.LookPath(termuxClipboardGet); err == nil { - return - } - } - - Unsupported = true -} - -func getPasteCommand() *exec.Cmd { - if Primary { - pasteCmdArgs = pasteCmdArgs[:1] - } - return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...) -} - -func getCopyCommand() *exec.Cmd { - if Primary { - copyCmdArgs = copyCmdArgs[:1] - } - return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...) -} - -func ReadAll() (string, error) { - if Unsupported { - return "", missingCommands - } - pasteCmd := getPasteCommand() - out, err := pasteCmd.Output() - if err != nil { - return "", err - } - return string(out), nil -} - -func WriteAll(text string) error { - if Unsupported { - return missingCommands - } - copyCmd := getCopyCommand() - in, err := copyCmd.StdinPipe() - if err != nil { - return err - } - - if err := copyCmd.Start(); err != nil { - return err - } - if _, err := in.Write([]byte(text)); err != nil { - return err - } - if err := in.Close(); err != nil { - return err - } - return copyCmd.Wait() -} diff --git a/server/internal/websocket/control.go b/server/internal/websocket/control.go index c34af5cf..2a7f91c3 100644 --- a/server/internal/websocket/control.go +++ b/server/internal/websocket/control.go @@ -1,7 +1,7 @@ package websocket import ( - "n.eko.moe/neko/internal/hid/clipboard" + "n.eko.moe/neko/internal/clip" "n.eko.moe/neko/internal/types" "n.eko.moe/neko/internal/types/event" "n.eko.moe/neko/internal/types/message" @@ -113,6 +113,6 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl return nil } - clipboard.WriteAll(payload.Text) + clip.Write(payload.Text) return nil } diff --git a/server/internal/websocket/websocket.go b/server/internal/websocket/websocket.go index eb052b85..5ba84ac6 100644 --- a/server/internal/websocket/websocket.go +++ b/server/internal/websocket/websocket.go @@ -9,7 +9,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "n.eko.moe/neko/internal/hid/clipboard" + "n.eko.moe/neko/internal/clip" "n.eko.moe/neko/internal/types" "n.eko.moe/neko/internal/types/config" "n.eko.moe/neko/internal/types/event" @@ -81,11 +81,7 @@ func (ws *WebSocketHandler) Start() error { ws.logger.Info().Msg("shutdown") }() - current := "" - clip, err := clipboard.ReadAll() - if err == nil && clip != current { - current = clip - } + current := clip.Read() for { select { @@ -93,16 +89,16 @@ func (ws *WebSocketHandler) Start() error { return default: if ws.sessions.HasHost() { - clip, err := clipboard.ReadAll() - if err == nil && clip != current { + text := clip.Read() + if text != current { session, ok := ws.sessions.GetHost() if ok { session.Send(message.Clipboard{ Event: event.CONTROL_CLIPBOARD, - Text: clip, + Text: text, }) } - current = clip + current = text } } time.Sleep(100 * time.Millisecond)