summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go303
1 files changed, 0 insertions, 303 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go
deleted file mode 100644
index 327c5c5..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/clipboard/watch.go
+++ /dev/null
@@ -1,303 +0,0 @@
-package clipboard
-
-import (
- "context"
- "errors"
- "fmt"
- "io"
- "os"
- "time"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/ext_data_control"
- wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
-)
-
-type ClipboardChange struct {
- Data []byte
- MimeType string
- MimeTypes []string
-}
-
-func Watch(ctx context.Context, callback func(data []byte, mimeType string)) error {
- display, err := wlclient.Connect("")
- if err != nil {
- return fmt.Errorf("wayland connect: %w", err)
- }
- defer display.Destroy()
-
- wlCtx := display.Context()
- registry, err := display.GetRegistry()
- if err != nil {
- return fmt.Errorf("get registry: %w", err)
- }
- defer registry.Destroy()
-
- var dataControlMgr *ext_data_control.ExtDataControlManagerV1
- var seat *wlclient.Seat
- var bindErr error
-
- registry.SetGlobalHandler(func(e wlclient.RegistryGlobalEvent) {
- switch e.Interface {
- case "ext_data_control_manager_v1":
- dataControlMgr = ext_data_control.NewExtDataControlManagerV1(wlCtx)
- if err := registry.Bind(e.Name, e.Interface, e.Version, dataControlMgr); err != nil {
- bindErr = err
- }
- case "wl_seat":
- if seat != nil {
- return
- }
- seat = wlclient.NewSeat(wlCtx)
- if err := registry.Bind(e.Name, e.Interface, e.Version, seat); err != nil {
- bindErr = err
- }
- }
- })
-
- display.Roundtrip()
- display.Roundtrip()
-
- if bindErr != nil {
- return fmt.Errorf("registry bind: %w", bindErr)
- }
-
- if dataControlMgr == nil {
- return fmt.Errorf("compositor does not support ext_data_control_manager_v1")
- }
- defer dataControlMgr.Destroy()
-
- if seat == nil {
- return fmt.Errorf("no seat available")
- }
-
- device, err := dataControlMgr.GetDataDevice(seat)
- if err != nil {
- return fmt.Errorf("get data device: %w", err)
- }
- defer device.Destroy()
-
- offerMimeTypes := make(map[*ext_data_control.ExtDataControlOfferV1][]string)
-
- device.SetDataOfferHandler(func(e ext_data_control.ExtDataControlDeviceV1DataOfferEvent) {
- if e.Id == nil {
- return
- }
- offerMimeTypes[e.Id] = nil
- e.Id.SetOfferHandler(func(me ext_data_control.ExtDataControlOfferV1OfferEvent) {
- offerMimeTypes[e.Id] = append(offerMimeTypes[e.Id], me.MimeType)
- })
- })
-
- device.SetSelectionHandler(func(e ext_data_control.ExtDataControlDeviceV1SelectionEvent) {
- if e.Id == nil {
- return
- }
-
- mimes := offerMimeTypes[e.Id]
- selectedMime := selectPreferredMimeType(mimes)
- if selectedMime == "" {
- return
- }
-
- r, w, err := os.Pipe()
- if err != nil {
- return
- }
-
- if err := e.Id.Receive(selectedMime, int(w.Fd())); err != nil {
- w.Close()
- r.Close()
- return
- }
- w.Close()
-
- go func() {
- defer r.Close()
- data, err := io.ReadAll(r)
- if err != nil || len(data) == 0 {
- return
- }
- callback(data, selectedMime)
- }()
- })
-
- display.Roundtrip()
- display.Roundtrip()
-
- for {
- select {
- case <-ctx.Done():
- return ctx.Err()
- default:
- if err := wlCtx.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
- return fmt.Errorf("set read deadline: %w", err)
- }
- if err := wlCtx.Dispatch(); err != nil {
- if isTimeoutError(err) {
- continue
- }
- return fmt.Errorf("dispatch: %w", err)
- }
- }
- }
-}
-
-func WatchAll(ctx context.Context, callback func(data []byte, mimeType string, allMimeTypes []string)) error {
- display, err := wlclient.Connect("")
- if err != nil {
- return fmt.Errorf("wayland connect: %w", err)
- }
- defer display.Destroy()
-
- wlCtx := display.Context()
- registry, err := display.GetRegistry()
- if err != nil {
- return fmt.Errorf("get registry: %w", err)
- }
- defer registry.Destroy()
-
- var dataControlMgr *ext_data_control.ExtDataControlManagerV1
- var seat *wlclient.Seat
- var bindErr error
-
- registry.SetGlobalHandler(func(e wlclient.RegistryGlobalEvent) {
- switch e.Interface {
- case "ext_data_control_manager_v1":
- dataControlMgr = ext_data_control.NewExtDataControlManagerV1(wlCtx)
- if err := registry.Bind(e.Name, e.Interface, e.Version, dataControlMgr); err != nil {
- bindErr = err
- }
- case "wl_seat":
- if seat != nil {
- return
- }
- seat = wlclient.NewSeat(wlCtx)
- if err := registry.Bind(e.Name, e.Interface, e.Version, seat); err != nil {
- bindErr = err
- }
- }
- })
-
- display.Roundtrip()
- display.Roundtrip()
-
- if bindErr != nil {
- return fmt.Errorf("registry bind: %w", bindErr)
- }
- if dataControlMgr == nil {
- return fmt.Errorf("compositor does not support ext_data_control_manager_v1")
- }
- defer dataControlMgr.Destroy()
- if seat == nil {
- return fmt.Errorf("no seat available")
- }
-
- device, err := dataControlMgr.GetDataDevice(seat)
- if err != nil {
- return fmt.Errorf("get data device: %w", err)
- }
- defer device.Destroy()
-
- offerMimeTypes := make(map[*ext_data_control.ExtDataControlOfferV1][]string)
-
- device.SetDataOfferHandler(func(e ext_data_control.ExtDataControlDeviceV1DataOfferEvent) {
- if e.Id == nil {
- return
- }
- offerMimeTypes[e.Id] = nil
- e.Id.SetOfferHandler(func(me ext_data_control.ExtDataControlOfferV1OfferEvent) {
- offerMimeTypes[e.Id] = append(offerMimeTypes[e.Id], me.MimeType)
- })
- })
-
- device.SetSelectionHandler(func(e ext_data_control.ExtDataControlDeviceV1SelectionEvent) {
- if e.Id == nil {
- return
- }
-
- mimes := offerMimeTypes[e.Id]
- selectedMime := selectPreferredMimeType(mimes)
- if selectedMime == "" {
- return
- }
-
- mimesCopy := make([]string, len(mimes))
- copy(mimesCopy, mimes)
-
- r, w, err := os.Pipe()
- if err != nil {
- return
- }
-
- if err := e.Id.Receive(selectedMime, int(w.Fd())); err != nil {
- w.Close()
- r.Close()
- return
- }
- w.Close()
-
- go func() {
- defer r.Close()
- data, err := io.ReadAll(r)
- if err != nil || len(data) == 0 {
- return
- }
- callback(data, selectedMime, mimesCopy)
- }()
- })
-
- display.Roundtrip()
- display.Roundtrip()
-
- for {
- select {
- case <-ctx.Done():
- return ctx.Err()
- default:
- if err := wlCtx.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
- return fmt.Errorf("set read deadline: %w", err)
- }
- if err := wlCtx.Dispatch(); err != nil {
- if isTimeoutError(err) {
- continue
- }
- return fmt.Errorf("dispatch: %w", err)
- }
- }
- }
-}
-
-func isTimeoutError(err error) bool {
- if err == nil {
- return false
- }
- if errors.Is(err, os.ErrDeadlineExceeded) {
- return true
- }
- if netErr, ok := err.(interface{ Timeout() bool }); ok && netErr.Timeout() {
- return true
- }
- return false
-}
-
-func WatchChan(ctx context.Context) (<-chan ClipboardChange, <-chan error) {
- ch := make(chan ClipboardChange, 16)
- errCh := make(chan error, 1)
-
- go func() {
- defer close(ch)
- err := Watch(ctx, func(data []byte, mimeType string) {
- select {
- case ch <- ClipboardChange{Data: data, MimeType: mimeType}:
- default:
- }
- })
- if err != nil && err != context.Canceled {
- errCh <- err
- }
- close(errCh)
- }()
-
- time.Sleep(50 * time.Millisecond)
- return ch, errCh
-}