libclipboard
This commit is contained in:
parent
7253b5ac62
commit
ed6f6f5a93
@ -4,7 +4,7 @@ FROM debian:stretch-slim
|
|||||||
# cluster fuck of packages for neko, node, go and gstreamer
|
# cluster fuck of packages for neko, node, go and gstreamer
|
||||||
RUN set -eux; apt-get update; apt-get install -y --no-install-recommends \
|
RUN set -eux; apt-get update; apt-get install -y --no-install-recommends \
|
||||||
autoconf ca-certificates curl netbase wget \
|
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 \
|
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 \
|
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 \
|
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 GOPATH /go
|
||||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
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
|
# install Go tools w/module support
|
||||||
RUN set -eux; \
|
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_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/master/script-library/common-debian.sh"
|
||||||
ARG COMMON_SCRIPT_SHA="dev-mode"
|
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
|
# verify git, common tools / libs installed, add/modify non-root user, optionally install zsh
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
|
@ -7,19 +7,19 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.shell.linux": "/bin/bash",
|
"terminal.integrated.shell.linux": "/bin/bash",
|
||||||
"go.gopath": "/go"
|
"go.gopath": "/go"
|
||||||
},
|
},
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-vscode.go",
|
"ms-vscode.go",
|
||||||
"octref.vetur",
|
"octref.vetur",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"ms-vscode-remote.vscode-remote-extensionpack",
|
"ms-vscode-remote.vscode-remote-extensionpack",
|
||||||
"ms-vscode-remote.remote-containers",
|
"ms-vscode-remote.remote-containers",
|
||||||
"ms-azuretools.vscode-docker",
|
"ms-azuretools.vscode-docker",
|
||||||
"editorconfig.editorconfig",
|
"editorconfig.editorconfig",
|
||||||
"psioniq.psi-header",
|
|
||||||
"gruntfuggly.todo-tree",
|
"gruntfuggly.todo-tree",
|
||||||
"swyphcosmo.spellchecker",
|
"eamodio.gitlens",
|
||||||
"eamodio.gitlens"
|
"swyphcosmo.spellchecker"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
24
Dockerfile
24
Dockerfile
@ -1,5 +1,6 @@
|
|||||||
FROM debian:stretch-slim
|
FROM debian:stretch-slim
|
||||||
|
|
||||||
|
#
|
||||||
# avoid warnings by switching to noninteractive
|
# avoid warnings by switching to noninteractive
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
@ -7,9 +8,27 @@ ARG USERNAME=neko
|
|||||||
ARG USER_UID=1000
|
ARG USER_UID=1000
|
||||||
ARG USER_GID=$USER_UID
|
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
|
# install neko dependencies
|
||||||
RUN set -eux; apt-get update; \
|
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; \
|
apt-get install -y --no-install-recommends libxv1 libopus0 libvpx4; \
|
||||||
#
|
#
|
||||||
# create a non-root user
|
# create a non-root user
|
||||||
@ -31,15 +50,16 @@ RUN set -eux; apt-get update; \
|
|||||||
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
|
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
|
||||||
#
|
#
|
||||||
# clean up
|
# clean up
|
||||||
apt-get autoremove -y; \
|
|
||||||
apt-get clean -y; \
|
apt-get clean -y; \
|
||||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||||
|
|
||||||
|
#
|
||||||
# add gst to env
|
# add gst to env
|
||||||
ENV PATH=/gst/local/bin:$PATH
|
ENV PATH=/gst/local/bin:$PATH
|
||||||
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
||||||
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||||
|
|
||||||
|
#
|
||||||
# copy gst
|
# copy gst
|
||||||
COPY .build/gst/local /gst/local/
|
COPY .build/gst/local /gst/local/
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"remote.containers.defaultExtensions": [
|
"remote.containers.defaultExtensions": [
|
||||||
"ms-vscode.go",
|
"ms-vscode.go",
|
||||||
"octref.vetur",
|
"octref.vetur",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"ms-vscode-remote.vscode-remote-extensionpack",
|
"ms-vscode-remote.vscode-remote-extensionpack",
|
||||||
@ -40,8 +41,8 @@
|
|||||||
"ms-azuretools.vscode-docker",
|
"ms-azuretools.vscode-docker",
|
||||||
"editorconfig.editorconfig",
|
"editorconfig.editorconfig",
|
||||||
"gruntfuggly.todo-tree",
|
"gruntfuggly.todo-tree",
|
||||||
"swyphcosmo.spellchecker",
|
"eamodio.gitlens",
|
||||||
"eamodio.gitlens"
|
"swyphcosmo.spellchecker"
|
||||||
],
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
23
server/internal/clip/clip.c
Normal file
23
server/internal/clip/clip.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "clip.h"
|
||||||
|
|
||||||
|
#include <libclipboard.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
21
server/internal/clip/clip.go
Normal file
21
server/internal/clip/clip.go
Normal file
@ -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))
|
||||||
|
}
|
5
server/internal/clip/clip.h
Normal file
5
server/internal/clip/clip.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include <libclipboard.h>
|
||||||
|
|
||||||
|
clipboard_c *getClipboard(void);
|
||||||
|
void set_clipboard(char *src);
|
||||||
|
char * get_clipboard();
|
@ -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()
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
package websocket
|
package websocket
|
||||||
|
|
||||||
import (
|
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"
|
||||||
"n.eko.moe/neko/internal/types/event"
|
"n.eko.moe/neko/internal/types/event"
|
||||||
"n.eko.moe/neko/internal/types/message"
|
"n.eko.moe/neko/internal/types/message"
|
||||||
@ -113,6 +113,6 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clipboard.WriteAll(payload.Text)
|
clip.Write(payload.Text)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"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"
|
||||||
"n.eko.moe/neko/internal/types/config"
|
"n.eko.moe/neko/internal/types/config"
|
||||||
"n.eko.moe/neko/internal/types/event"
|
"n.eko.moe/neko/internal/types/event"
|
||||||
@ -81,11 +81,7 @@ func (ws *WebSocketHandler) Start() error {
|
|||||||
ws.logger.Info().Msg("shutdown")
|
ws.logger.Info().Msg("shutdown")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
current := ""
|
current := clip.Read()
|
||||||
clip, err := clipboard.ReadAll()
|
|
||||||
if err == nil && clip != current {
|
|
||||||
current = clip
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -93,16 +89,16 @@ func (ws *WebSocketHandler) Start() error {
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
if ws.sessions.HasHost() {
|
if ws.sessions.HasHost() {
|
||||||
clip, err := clipboard.ReadAll()
|
text := clip.Read()
|
||||||
if err == nil && clip != current {
|
if text != current {
|
||||||
session, ok := ws.sessions.GetHost()
|
session, ok := ws.sessions.GetHost()
|
||||||
if ok {
|
if ok {
|
||||||
session.Send(message.Clipboard{
|
session.Send(message.Clipboard{
|
||||||
Event: event.CONTROL_CLIPBOARD,
|
Event: event.CONTROL_CLIPBOARD,
|
||||||
Text: clip,
|
Text: text,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
current = clip
|
current = text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
Reference in New Issue
Block a user