feat(clipboard): add wayland support (#657)
Signed-off-by: xqrs <3bd3bdr@gmail.com> Co-authored-by: Ayyan <ayn2op@gmail.com>
This commit is contained in:
parent
b2a0e7f012
commit
9a83762580
9 changed files with 96 additions and 11 deletions
|
|
@ -44,10 +44,7 @@ go build .
|
|||
|
||||
### Wayland clipboard support
|
||||
|
||||
`x11-dev` is required for X11 clipboard compatibility:
|
||||
|
||||
- Ubuntu: `apt install xwayland`
|
||||
- Arch Linux: `pacman -S xorg-xwayland`
|
||||
`wl-clipboard` is required for clipboard support.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ package cmd
|
|||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/login"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
"golang.design/x/clipboard"
|
||||
)
|
||||
|
||||
type application struct {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"log/slog"
|
||||
"slices"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
"github.com/ayn2op/tview"
|
||||
|
|
@ -13,7 +14,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/ningen/v3"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
"golang.design/x/clipboard"
|
||||
)
|
||||
|
||||
type guildsTree struct {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"unicode"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/cache"
|
||||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/consts"
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
|
|
@ -29,7 +30,6 @@ import (
|
|||
"github.com/ncruces/zenity"
|
||||
"github.com/sahilm/fuzzy"
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"golang.design/x/clipboard"
|
||||
)
|
||||
|
||||
const tmpFilePattern = consts.Name + "_*.md"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/consts"
|
||||
"github.com/ayn2op/discordo/internal/markdown"
|
||||
|
|
@ -30,7 +31,6 @@ import (
|
|||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/text"
|
||||
"golang.design/x/clipboard"
|
||||
)
|
||||
|
||||
type messagesList struct {
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ func onReady(r *gateway.ReadyEvent) {
|
|||
|
||||
func onMessageCreate(message *gateway.MessageCreateEvent) {
|
||||
if app.chatView.selectedChannel != nil &&
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
app.chatView.messagesList.drawMessage(app.chatView.messagesList, message.Message)
|
||||
app.Draw()
|
||||
}
|
||||
|
|
@ -159,14 +159,14 @@ func onMessageCreate(message *gateway.MessageCreateEvent) {
|
|||
|
||||
func onMessageUpdate(message *gateway.MessageUpdateEvent) {
|
||||
if app.chatView.selectedChannel != nil &&
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
onMessageDelete(&gateway.MessageDeleteEvent{ID: message.ID, ChannelID: message.ChannelID, GuildID: message.GuildID})
|
||||
}
|
||||
}
|
||||
|
||||
func onMessageDelete(message *gateway.MessageDeleteEvent) {
|
||||
if app.chatView.selectedChannel != nil &&
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
app.chatView.selectedChannel.ID == message.ChannelID {
|
||||
messages, err := discordState.Cabinet.Messages(message.ChannelID)
|
||||
if err != nil {
|
||||
slog.Error("failed to get messages from state", "err", err, "channel_id", message.ChannelID)
|
||||
|
|
|
|||
10
internal/clipboard/clipboard.go
Normal file
10
internal/clipboard/clipboard.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package clipboard
|
||||
|
||||
import designClipb "golang.design/x/clipboard"
|
||||
|
||||
type Format = designClipb.Format
|
||||
|
||||
const (
|
||||
FmtText Format = designClipb.FmtText
|
||||
FmtImage = designClipb.FmtImage
|
||||
)
|
||||
11
internal/clipboard/clipboard_default.go
Normal file
11
internal/clipboard/clipboard_default.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//go:build !linux
|
||||
|
||||
package clipboard
|
||||
|
||||
import designClipb "golang.design/x/clipboard"
|
||||
|
||||
var (
|
||||
Init = designClipb.Init
|
||||
Read = designClipb.Read
|
||||
Write = designClipb.Write
|
||||
)
|
||||
67
internal/clipboard/clipboard_linux.go
Normal file
67
internal/clipboard/clipboard_linux.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//go:build linux
|
||||
|
||||
package clipboard
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
designClipb "golang.design/x/clipboard"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var wayland bool
|
||||
|
||||
func Init() error {
|
||||
if _, ok := os.LookupEnv("WAYLAND_DISPLAY"); !ok {
|
||||
return designClipb.Init()
|
||||
}
|
||||
if _, err := exec.LookPath("wl-copy"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := exec.LookPath("wl-paste"); err != nil {
|
||||
return err
|
||||
}
|
||||
wayland = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func Read(t Format) []byte {
|
||||
if !wayland {
|
||||
return designClipb.Read(designClipb.Format(t))
|
||||
}
|
||||
// -n: Don't print a newline at the end
|
||||
// -t type: MIME type specifier
|
||||
cmd := exec.Command("wl-paste", "-nt", formatToType(t))
|
||||
outBuffer := bytes.Buffer{}
|
||||
cmd.Stdout = &outBuffer
|
||||
if err := cmd.Run(); err != nil {
|
||||
slog.Error("failed to read clipboard", "err", err)
|
||||
return nil
|
||||
}
|
||||
return outBuffer.Bytes()
|
||||
}
|
||||
|
||||
func Write(t Format, buf []byte) <-chan struct{} {
|
||||
if !wayland {
|
||||
return designClipb.Write(designClipb.Format(t), buf)
|
||||
}
|
||||
// -t type: MIME type specifier
|
||||
cmd := exec.Command("wl-copy", "-t", formatToType(t))
|
||||
cmd.Stdin = bytes.NewReader(buf)
|
||||
if err := cmd.Run(); err != nil {
|
||||
slog.Error("failed to write to clipboard", "err", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatToType(t Format) string {
|
||||
switch t {
|
||||
case FmtImage:
|
||||
return "image"
|
||||
case FmtText:
|
||||
fallthrough
|
||||
default:
|
||||
return "text/plain;charset=utf-8"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue