diff --git a/BUILDING.md b/BUILDING.md deleted file mode 100644 index 0222fae..0000000 --- a/BUILDING.md +++ /dev/null @@ -1,63 +0,0 @@ -# Building - -wl-clipboard is a simple Meson project, so building it is just: - -```bash -# Clone: -$ git clone https://github.com/bugaevc/wl-clipboard.git -$ cd wl-clipboard - -# Build: -$ meson setup build -$ cd build -$ ninja - -# Install -$ sudo meson install -``` - -wl-clipboard supports Linux and BSD systems, and is also known to work on -Mac OS X and GNU Hurd. The only mandatory dependency is the `wayland-client` -library (try package named `wayland-devel` or `libwayland-dev`). - -Optional (but highly recommended) dependencies for building: -* `wayland-scanner` -* `wayland-protocols` (version 1.12 or later) - -If these are found during configuration, wl-clipboard gets built with -additional protocols support, which enables features such as primary selection -support and `--watch` mode. If they are not found, Meson can optionally build -them on the spot as subprojects. - -Note that many compositors have dropped support for the `wl_shell` interface, -which means wl-clipboard will not work under them unless built with both -`wayland-scanner` and `wayland-protocols`. For this reason, you have to -explicitly opt into allowing building without these dependencies by specifying -`-D protocols=auto` (or `-D protocols=disabled`) when configuring with Meson. - -Optional dependencies for running: -* `xdg-mime` for content type inference in `wl-copy` (try package named - `xdg-utils`) -* `/etc/mime.types` file for type inference in `wl-paste` (try package named - `mime-support` or `mailcap`) -* `/usr/share/mime/globs2` file for for type inference in `wl-paste` (try - packaged named `shared-mime-info`) - -If you're packaging wl-clipboard for a distribution, please consider making -packages providing `xdg-mime`, `/etc/mime.types`, and `/usr/share/mime/globs2` -*weak* dependencies of the package providing wl-clipboard, meaning ones that -get installed along with wl-clipboard by default, but are not strictly required -by it. - -A package definition for wl-clipboard might therefore contain something along -the following lines: - -``` -Package: wl-clipboard -Build-Depends: - gcc, meson, ninja, - wayland-devel, wayland-scanner, - wayland-protocols >= 1.12 -Recommends: - xdg-utils, mime-support, shared-mime-info -``` diff --git a/README.md b/README.md index b0ebd16..915db62 100644 --- a/README.md +++ b/README.md @@ -4,35 +4,96 @@ This project implements two command-line Wayland clipboard utilities, `wl-copy` and `wl-paste`, that let you easily copy data between the clipboard and Unix pipes, sockets, files and so on. +Usage is as simple as: + ```bash -# Copy a simple text message: +# copy a simple text message $ wl-copy Hello world! -# Copy the list of files in ~/Downloads: +# copy the list of files in Downloads $ ls ~/Downloads | wl-copy -# Copy an image: +# copy an image file $ wl-copy < ~/Pictures/photo.png -# Copy the previous command: -$ wl-copy "!!" - -# Paste to a file: +# paste to a file $ wl-paste > clipboard.txt -# Sort clipboard contents: -$ wl-paste | sort | wl-copy +# grep each pasted word in file source.c +$ for word in $(wl-paste); do grep $word source.c; done -# Upload clipboard contents to a pastebin on each change: -$ wl-paste --watch nc paste.example.org 5555 +# copy the previous command +$ wl-copy "!!" + +# replace the current selection with the list of types it's offered in +$ wl-paste --list-types | wl-copy ``` -Please see the wl-clipboard(1) man page for more details. +Although `wl-copy` and `wl-paste` are particularly optimized for plain text and +other textual content formats, they fully support content of arbitrary MIME +types. `wl-copy` automatically infers the type of the copied content by running +`xdg-mime(1)` on it. `wl-paste` tries its best to pick a type to paste based on +the list of offered MIME types and the extension of the file it's pasting into. +If you're not satisfied with the type they pick or don't want to rely on this +implicit type inference, you can explicitly specify the type to use with the +`--type` option. -# Installing +# Options -wl-clipboard is likely available in your favorite Linux or BSD distro. For -building from source, see [BUILDING.md](BUILDING.md). +For `wl-copy`: + +* `-n`, `--trim-newline` Do not copy the trailing newline character if it is present in the input file. +* `-o`, `--paste-once` Only serve one paste request and then exit. Unless a clipboard manager specifically designed to prevent this is in use, this has the effect of clearing the clipboard after the first paste, which is useful for copying sensitive data such as passwords. Note that this may break pasting into some clients, in particular pasting into XWayland windows is known to break when this option is used. +* `-f`, `--foreground` By default, `wl-copy` forks and serves data requests in the background; this option overrides that behavior, causing `wl-copy` to run in the foreground. +* `-c`, `--clear` Instead of copying anything, clear the clipboard so that nothing is copied. + +For `wl-paste`: + +* `-n`, `--no-newline` Do not append a newline character after the pasted clipboard content. This option is automatically enabled for non-text content types and when using the `--watch` mode. +* `-l`, `--list-types` Instead of pasting the selection, output the list of MIME types it is offered in. +* `-w command...`, `--watch command...` Instead of pasting once and exiting, continuously watch the clipboard for changes, and run the specified command each time a new selection appears. The spawned process can read the clipboard contents from its standard input. This mode requires a compositor that supports the [wlroots data-control protocol](https://github.com/swaywm/wlr-protocols/blob/master/unstable/wlr-data-control-unstable-v1.xml). + +For both: + +* `-p`, `--primary` Use the "primary" clipboard instead of the regular clipboard. +* `-t mime/type`, `--type mime/type` Override the inferred MIME type for the content. For `wl-copy` this option controls which type `wl-copy` will offer the content as. For `wl-paste` it controls which of the offered types `wl-paste` will request the content in. In addition to specific MIME types such as _image/png_, `wl-paste` also accepts generic type names such as _text_ and _image_ which make it automatically pick some offered MIME type that matches the given generic name. +* `-s seat-name`, `--seat seat-name` Specify which seat `wl-copy` and `wl-paste` should work with. Wayland natively supports multi-seat configurations where each seat gets its own mouse pointer, keyboard focus, and among other things its own separate clipboard. The name of the default seat is likely _default_ or _seat0_, and additional seat names normally come form `udev(7)` property `ENV{WL_SEAT}`. You can view the list of the currently available seats as advertised by the compositor using the `weston-info(1)` tool. If you don't specify the seat name explicitly, `wl-copy` and `wl-paste` will pick a seat arbitrarily. If you are using a single-seat system, there is little reason to use this option. +* `-v`, `--version` Display the version of wl-clipboard and some short info about its license. +* `-h`, `--help` Display a short help message listing the available options. + +# Building + +wl-clipboard is a simple Meson project, so building it is just: + +```bash +# clone +$ git clone https://github.com/bugaevc/wl-clipboard.git +$ cd wl-clipboard + +# build +$ meson build +$ cd build +$ ninja + +# install +$ sudo ninja install +``` + +wl-clipboard supports Linux and BSD systems, and is also known to work on +Mac OS X and GNU Hurd. The only mandatory dependency is the `wayland-client` +library (try package named `wayland-devel` or `libwayland-dev`). + +Optional dependencies for building: +* `wayland-scanner` +* `wayland-protocols` (version 1.12 or later) + +If these are found during configuration, wl-clipboard gets built with +additional protocols support, which enables features such as primary selection +support and `--watch` mode. + +Optional dependencies for running: +* `xdg-mime` for content type inference in `wl-copy` (try package named `xdg-utils`) +* `/etc/mime.types` file for type inference in `wl-paste` (try package named `mime-support` or `mailcap`) # License @@ -41,8 +102,5 @@ version 3 or later. # Related projects -* [wl-clipboard-x11](https://github.com/brunelli/wl-clipboard-x11): A wrapper to - use wl-clipboard as a drop-in replacement to X11 clipboard tools. -* [wl-clipboard-rs](https://github.com/YaLTeR/wl-clipboard-rs): A Rust crate - (library) for working with the Wayland clipboard which includes a - reimplementation of `wl-copy` and `wl-paste`. +* [wl-clipboard-x11](https://github.com/brunelli/wl-clipboard-x11): A wrapper to use wl-clipboard as a drop-in replacement to X11 clipboard tools. +* [wl-clipboard-rs](https://github.com/YaLTeR/wl-clipboard-rs): A Rust crate (library) for working with the Wayland clipboard which includes a reimplementation of `wl-copy` and `wl-paste`. diff --git a/completions/fish/meson.build b/completions/fish/meson.build deleted file mode 100644 index cb1280c..0000000 --- a/completions/fish/meson.build +++ /dev/null @@ -1,22 +0,0 @@ -fish_completion_dir = get_option('fishcompletiondir') -fish = dependency('fish', required : false) - -if fish_completion_dir == '' and fish.found() - if meson.version().version_compare('>= 0.58') - fish_completion_dir = fish.get_variable('completionsdir') - else - fish_completion_dir = fish.get_pkgconfig_variable('completionsdir') - endif -elif fish_completion_dir == '' - # Fish does not look in /usr/local/, which is the default prefix, - # so we cannot use get_option("datadir"). Instead, they recommend - # custom completions to be installed into /usr/share/fish/vendor_completions.d, - # so we use that. Note that this is a fallback in case you neither - # have fish installed, nor have specified a path explicitly - fish_completion_dir = '/usr/share/fish/vendor_completions.d' -endif - -if fish_completion_dir != 'no' - install_data('wl-copy.fish', install_dir: fish_completion_dir) - install_data('wl-paste.fish', install_dir: fish_completion_dir) -endif diff --git a/completions/fish/wl-copy.fish b/completions/fish/wl-copy.fish deleted file mode 100644 index dafd32a..0000000 --- a/completions/fish/wl-copy.fish +++ /dev/null @@ -1,21 +0,0 @@ -function __wayland_seats --description 'Print all wayland seats' - if type -q weston-info - weston-info 2>/dev/null | sed -n '/wl_seat/{n;s/\s*name: //;p}' - else if type -q loginctl - loginctl --no-legend --no-pager list-seats 2>/dev/null - else - # Fallback seat - echo "seat0" - end - -end - -complete -c wl-copy -x -complete -c wl-copy -s h -l help -d 'Display a help message' -complete -c wl-copy -s v -l version -d 'Display version info' -complete -c wl-copy -s o -l paste-once -d 'Only serve one paste request and then exit' -complete -c wl-copy -s c -l clear -d 'Instead of copying anything, clear the clipboard' -complete -c wl-copy -s p -l primary -d 'Use the "primary" clipboard' -complete -c wl-copy -s n -l trim-newline -d 'Do not copy the trailing newline character' -complete -c wl-copy -s t -l type -x -d 'Override the inferred MIME type for the content' -a "(__fish_print_xdg_mimetypes)" -complete -c wl-copy -s s -l seat -x -d 'Pick the seat to work with' -a "(__wayland_seats)" diff --git a/completions/fish/wl-paste.fish b/completions/fish/wl-paste.fish deleted file mode 100644 index 04df3a4..0000000 --- a/completions/fish/wl-paste.fish +++ /dev/null @@ -1,46 +0,0 @@ -function __wayland_seats --description 'Print all wayland seats' - if type -q weston-info - weston-info 2>/dev/null | sed -n '/wl_seat/{n;s/\s*name: //;p}' - else if type -q loginctl - loginctl --no-legend --no-pager list-seats 2>/dev/null - else - # Fallback seat - echo "seat0" - end -end - -function __wl_paste_types --description 'Print types with context' - set -l type (commandline -o) - - for i in (seq (count $type)) - if [ "$type[$i]" = '--primary' ]; or [ "$type[$i]" = '-p' ] - set clip "primary" - else if [ "$type[$i]" = '--seat' ]; or [ "$type[$i]" = '-s' ] - set seat $type[(math $i + 1)] - end - end - - # Note fish does not handle passing unset variables - # to commands well, thus setting clip to "--primary" and passing - # that to wl-paste won't work, so if statements are used instead - if test -n "$seat"; and test -n "$clip" - wl-paste 2>/dev/null --seat "$seat" -p -l - else if test -n "$seat" - wl-paste 2>/dev/null --seat "$seat" -l - else if test -n "$clip" - wl-paste 2>/dev/null -p -l - else - wl-paste 2>/dev/null -l - end -end - -complete -c wl-paste -f -complete -c wl-paste -f -n '__fish_contains_opt -s w watch' -a "(__fish_complete_subcommand -- -s --seat -t --type)" -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s h -l help -d 'Display a help message' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s v -l version -d 'Display version info' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s n -l no-newline -d 'Do not append a newline character' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s l -l list-types -d 'Instead of pasting, list the offered types' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s p -l primary -d 'Use the "primary" clipboard' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s w -l watch -d 'Run a command each time the selection changes' -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s t -l type -x -d 'Override the inferred MIME type for the content' -a "(__wl_paste_types)" -complete -c wl-paste -n '__fish_not_contain_opt -s w watch' -s s -l seat -x -d 'Pick the seat to work with' -a "(__wayland_seats)" diff --git a/completions/meson.build b/completions/meson.build index 96542c5..3cce95b 100644 --- a/completions/meson.build +++ b/completions/meson.build @@ -1,3 +1,2 @@ subdir('bash') subdir('zsh') -subdir('fish') diff --git a/completions/zsh/_wl-copy b/completions/zsh/_wl-copy index 197a5b0..5fd9bd7 100644 --- a/completions/zsh/_wl-copy +++ b/completions/zsh/_wl-copy @@ -22,7 +22,7 @@ __all_seats() { fi if [[ -z $seats ]]; then - # seat0 is always a valid seat and covers most cases, so it's a good fallback. + # seat0 is always a vaild seat and covers most cases, so its a good fallback. compadd "$@" - seat0 else compadd "$@" -a seats diff --git a/completions/zsh/_wl-paste b/completions/zsh/_wl-paste index 852d630..a402d30 100644 --- a/completions/zsh/_wl-paste +++ b/completions/zsh/_wl-paste @@ -1,13 +1,12 @@ #compdef wl-paste -local expl -typeset -A opt_args - _wl-paste_types() { local -a types args args=( - ${(kv)opt_args[(I)-p|--primary]} - ${(kv)opt_args[(I)-s|--seat]} + ${(k)opt_args[-p]} + ${(k)opt_args[--primary]} + ${(k)opt_args[-s]} ${(v)opt_args[-s]} + ${(k)opt_args[--seat]} ${(v)opt_args[--seat]} ) types=( ${(@f)"$(wl-paste $args -l 2>/dev/null)"} ) @@ -24,18 +23,19 @@ __all_seats() { fi if [[ -z $seats ]]; then - # seat0 covers most cases, so its a good fallback. + # seat0 is always a vaild seat and covers most cases, so its a good fallback. compadd "$@" - seat0 else compadd "$@" -a seats fi } +typeset -A opt_args _arguments -S -s \ {-n,--no-newline}'[Do not append a newline character]' \ {-l,--list-types}'[Instead of pasting, list the offered types]' \ {-p,--primary}'[Use the "primary" clipboard]' \ - {-w,--watch}'[Run a command wach time the selection changes]:*::command:_normal' \ + {-w+,--watch=}'[Run a command wach time the selection changes]:*::command:_normal' \ {-t+,--type=}'[Override the inferred MIME type for the content]:mimetype:_wl-paste_types' \ {-s+,--seat=}'[Pick the seat to work with]:seat:__all_seats' \ {-v,--version}'[Display version info]' \ diff --git a/completions/zsh/meson.build b/completions/zsh/meson.build index dc2820d..0ae6a08 100644 --- a/completions/zsh/meson.build +++ b/completions/zsh/meson.build @@ -1,9 +1,4 @@ -zsh_completion_dir = get_option('zshcompletiondir') -if zsh_completion_dir == '' - zsh_completion_dir = join_paths(get_option('datadir'), 'zsh', 'site-functions') -endif +zsh_completion_dir = join_paths(get_option('datadir'), 'zsh', 'site-functions') -if zsh_completion_dir != 'no' - install_data('_wl-copy', install_dir: zsh_completion_dir) - install_data('_wl-paste', install_dir: zsh_completion_dir) -endif +install_data('_wl-copy', install_dir: zsh_completion_dir) +install_data('_wl-paste', install_dir: zsh_completion_dir) diff --git a/data/wl-clipboard.1 b/data/wl-clipboard.1 index 4243a91..93feed9 100644 --- a/data/wl-clipboard.1 +++ b/data/wl-clipboard.1 @@ -1,17 +1,24 @@ -.TH WL-CLIPBOARD 1 2026-08-06 wl-clipboard +.TH WL-CLIPBOARD 1 2019-09-16 wl-clipboard .SH NAME wl-clipboard \- Wayland copy and paste command line utilities .SH SYNOPSIS .B wl-copy -[\fB\-\-primary\fR] -[\fB\-\-type \fImime/type\fR] +[\fB--primary\fR] +[\fB--trim-newline\fR] +[\fB--paste-once\fR] +[\fB--foreground\fR] +[\fB--clear\fR] +[\fB--type \fImime/type\fR] +[\fB--seat \fIseat-name\fR] [\fItext\fR...] .PP .B wl-paste -[\fB\-\-primary\fR] -[\fB\-\-type \fImime/type\fR] -.PP -Only the most useful options are listed here; see below for the full list. +[\fB--primary\fR] +[\fB--no-newline\fR] +[\fB--list-types\fR] +[\fB--type \fImime/type\fR] +[\fB--seat \fIseat-name\fR] +[\fB--watch \fIcommand\fR...\] .SH DESCRIPTION \fBwl-copy\fR copies the given \fItext\fR to the Wayland clipboard. If no \fItext\fR is given, \fBwl-copy\fR copies data from its standard input. @@ -25,43 +32,36 @@ running \fBxdg-mime\fR(1) on it. \fBwl-paste\fR tries its best to pick a type to paste based on the list of offered MIME types and the extension of the file it's pasting into. If you're not satisfied with the type they pick or don't want to rely on this implicit type inference, you can explicitly specify the type to use -with the \fB\-\-type\fR option. +with the \fB--type\fR option. .SH OPTIONS -To parse options, wl-clipboard uses the -.BR getopt (3) -library routines, whose features depend on the C library in use. In particular, -it may be possible to specify \fB\-\-\fR as an argument on its own to prevent -any further arguments from getting parsed as options (which lets you copy text -containing words that start with the \fB-\fR sign), and to shorten long options -to their unambiguous prefixes. .TP -\fB\-p\fR, \fB\-\-primary +\fB-p\fR, \fB--primary Use the "primary" clipboard instead of the regular clipboard. .TP -\fB\-o\fR, \fB\-\-paste-once\fR (for \fBwl-copy\fR) +\fB-o\fR, \fB--paste-once Only serve one paste request and then exit. Unless a clipboard manager specifically designed to prevent this is in use, this has the effect of clearing the clipboard after the first paste, which is useful for copying sensitive data -such as passwords. Note that this may break pasting into some clients that -expect to be able to paste multiple times, in particular pasting into XWayland -windows is known to break when this option is used. +such as passwords. Note that this may break pasting into some clients, in +particular pasting into XWayland windows is known to break when this option is +used. .TP -\fB\-f\fR, \fB\-\-foreground\fR (for \fBwl-copy\fR) +\fB-f\fR, \fB--foreground By default, \fBwl-copy\fR forks and serves data requests in the background; this option overrides that behavior, causing \fBwl-copy\fR to run in the foreground. .TP -\fB\-c\fR, \fB\-\-clear\fR (for \fBwl-copy\fR) +\fB-c\fR, \fB--clear Instead of copying anything, clear the clipboard so that nothing is copied. .TP -\fB\-n\fR, \fB\-\-trim-newline\fR (for \fBwl-copy\fR) +\fB-n\fR, \fB--trim-newline Do not copy the trailing newline character if it is present in the input file. .TP -\fB\-n\fR, \fB\-\-no-newline\fR (for \fBwl-paste\fR) +\fB-n\fR, \fB--no-newline Do not append a newline character after the pasted clipboard content. This option is automatically enabled for non-text content types and when using the -\fB\-\-watch\fR mode. +\fB--watch\fR mode. .TP -\fB\-t\fI mime/type\fR, \fB\-\-type\fI mime/type +\fB-t\fI mime/type\fR, \fB--type\fI mime/type Override the automatically selected MIME type. For \fBwl-copy\fR this option controls which type \fBwl-copy\fR will offer the content as. For \fBwl-paste\fR it controls which of the offered types \fBwl-paste\fR will request the content @@ -69,7 +69,7 @@ in. In addition to specific MIME types such as \fIimage/png\fR, \fBwl-paste\fR also accepts generic type names such as \fItext\fR and \fIimage\fR which make it automatically pick some offered MIME type that matches the given generic name. .TP -\fB\-s\fI seat-name\fR, \fB\-\-seat\fI seat-name +\fB-s\fI seat-name\fR, \fB--seat\fI seat-name Specify which seat \fBwl-copy\fR and \fBwl-paste\fR should work with. Wayland natively supports multi-seat configurations where each seat gets its own mouse pointer, keyboard focus, and among other things its own separate clipboard. The @@ -83,33 +83,24 @@ tool. If you don't specify the seat name explicitly, \fBwl-copy\fR and \fBwl-paste\fR will pick a seat arbitrarily. If you are using a single-seat system, there is little reason to use this option. .TP -\fB\-l\fR, \fB\-\-list-types\fR (for \fBwl-paste\fR) +\fB-l\fR, \fB--list-types Instead of pasting the selection, output the list of MIME types it is offered in. .TP -\fB\-w\fI command\fR..., \fB\-\-watch \fIcommand\fR... (for \fBwl-paste\fR) +\fB-w\fI command\fR..., \fB--watch \fIcommand\fR... Instead of pasting once and exiting, continuously watch the clipboard for changes, and run the specified \fIcommand\fR each time a new selection appears. The spawned process can read the clipboard contents from its standard input. -\fBwl-paste\fR also sets the \fBCLIPBOARD_STATE\fR and \fBCLIPBOARD_TYPE\fR -variables in the environment of the spawned processes (see below). -.IP This mode requires a compositor that supports the wlroots data-control protocol. .TP -\fB\-\-sensitive\fR (for \fBwl-copy\fR) -Hint that the data being copied contains passwords, keys, or other sensitive -content. Some clipboard managers may react by not persisting the copied data in -the clipboard history. This corresponds to \fBCLIPBOARD_STATE=sensitive\fR (see -below). -.TP -\fB\-v\fR, \fB\-\-version +\fB-v\fR, \fB--version Display the version of wl-clipboard and some short info about its license. .TP -\fB\-h\fR, \fB\-\-help +\fB-h\fR, \fB--help Display a short help message listing the available options. .SH ENVIRONMENT .TP -.B WAYLAND_DISPLAY +WAYLAND_DISPLAY Specifies what Wayland server \fBwl-copy\fR and \fBwl-paste\fR should connect to. This is the same environment variable that you pass to other Wayland clients, such as graphical applications, that connect to this Wayland server. It @@ -118,144 +109,34 @@ compositor. See .BR wl_display_connect (3) for more details. .TP -.B WAYLAND_DEBUG +WAYLAND_DEBUG When set to \fB1\fR, causes the \fBwayland-client\fR(7) library to log every interaction \fBwl-copy\fR and \fBwl-paste\fR make with the Wayland compositor to stderr. -.TP -.B CLIPBOARD_STATE -Set by \fBwl-paste\fR for the spawned command in \fB\-\-watch\fR mode. Currently -the following possible values are \fIdefined\fR: -.RS -.TP -CLIPBOARD_STATE=\fBdata -Indicates that the clipboard contains data that the spawned command can read -from its standard input. This is the most common case. -.TP -CLIPBOARD_STATE=\fBnil -Indicates that the clipboard is empty. In this case the spawned command's -standard input will be attached to \fI/dev/null\fR. Note that this is subtly -different from the clipboard containing zero-sized data (which can be achieved, -for instance, by running \fBwl-copy < /dev/null\fR). -.TP -CLIPBOARD_STATE=\fBclear -Indicates that the clipboard is empty because of an explicit clear request, such -as after running \fBwl-copy --clear\fR. As for \fBnil\fR, the command's standard -input will be attached to \fI/dev/null\fR. -.TP -CLIPBOARD_STATE=\fBsensitive -Indicates that the clipboard contains sensitive data such as a password or a -key. It is probably best to avoid visibly displaying or persistently saving -clipboard contents. -.RE -.IP -Any client programs implementing the \fBCLIPBOARD_STATE\fR protocol are -encouraged to implement proper support for all the values listed above, as well -as to fall back to some sensible behavior if \fBCLIPBOARD_STATE\fR is unset or -set to some unrecognized value (this is to leave the design space open for -future extensions). However, the currently existing Wayland clipboard protocols -don't let wl-clipboard identify the cases where \fBclear\fR and \fBsensitive\fR -values should be set. For this reason, currently, wl-clipboard never actually -sets \fBCLIPBOARD_STATE\fR to \fBclear\fR, and only sets it to \fBsensitive\fR -when it encounters \fBx-kde-passwordManagerHint\fR among the MIME types. -.IP -The \fBCLIPBOARD_STATE\fR protocol was intentionally designed to not be specific -to either wl-clipboard or Wayland; in fact, other clipboard tools are encouraged -to implement the same protocol. Currently, the SerenityOS -.BR paste (1) -utility is known to implement the same \fBCLIPBOARD_STATE\fR protocol. -.TP -.B CLIPBOARD_TYPE -Set by \fBwl-paste\fR for the spawned command in \fB\-\-watch\fR mode to the -MIME type of the data on its standard input, such as \fBimage/png\fR. Left -unset when there is no data to read, such as when the clipboard is empty. -.SH FILES -.TP -\fI/etc/mime.types\fR, \fI/usr/share/mime/globs2\fR -If present, read by \fBwl-paste\fR to infer the MIME type to paste in based on -the file name extension of its standard output. -.SH BUGS -Unless the Wayland compositor implements the wlroots data-control protocol, -wl-clipboard has to resort to using a hack to access the clipboard: it will -briefly pop up a tiny transparent surface (window). On some desktop -environments (in particular when using tiling window managers), this can cause -visual issues such as brief flashing. In some cases the Wayland compositor -doesn't give focus to the popup surface, which prevents wl-clipboard from -accessing the clipboard and manifests as a hang. -.PP -There is currently no way to copy data in multiple MIME types, such as multiple -image formats, at the same time. -.br -See -.nh -. -.hy -.PP -wl-clipboard is not always able to detect that a MIME type is textual, which may -break pasting into clients that expect textual formats, not -\fIapplication/something\fR. The workaround, same as for all format inference -issues, is to specify the desired MIME type explicitly, such as -\fBwl-copy \-\-type\fI text/plain\fR. -.PP -\fBwl-copy \-\-clear\fR and \fBwl-copy \-\-paste-once\fR don't always interact -well with clipboard managers that are overeager to preserve clipboard contents. -.PP -Applications written using the GTK 3 toolkit copy text with \(dq\er\en\(dq (also -known as CR LF) line endings, which takes most other software by surprise. -wl-clipboard does nothing to rectify this. The recommended workaround is piping -\fBwl-paste\fR output through -.BR dos2unix (1) -when pasting from a GTK 3 application. -.br -See -.nh -. -.hy -.PP -When trying to paste content copied with \fBwl-copy\fR, \fBwl-copy\fR does not -check whether the requested MIME type is among those it has offered, and always -provides the same data in response. .SH EXAMPLES -.TP -Copy a simple text message: $ .BI wl-copy " Hello world!" -.TP -Copy a message starting with dashes: -.BI "wl-copy -- " --long -.TP -Copy the list of files in \fI~/Downloads\fR: +.PP $ .IB "ls ~/Downloads" " | wl-copy" -.TP -Copy an image: +.PP $ .BI "wl-copy < " ~/Pictures/photo.png -.TP -Copy the previous command: +.PP $ .B wl-copy \(dq!!\(dq -.TP -Paste to a file, without appending a newline: +.PP $ -.BI "wl-paste \-n > " clipboard.txt -.TP -Sort clipboard contents: +.BI "wl-paste -n > " clipboard.txt +.PP $ -.B wl-paste | sort | wl-copy -.TP -Upload clipboard contents to a pastebin on each change: -$ -.BI "wl-paste --watch nc " "paste.example.org 5555 +.B wl-paste --list-types | wl-copy .SH AUTHOR Written by Sergey Bugaev. .SH REPORTING BUGS Report wl-clipboard bugs to -.br -Please make sure to mention which Wayland compositor you are using, and attach -\fBWAYLAND_DEBUG=1\fR debugging logs of wl-clipboard. .SH COPYRIGHT -Copyright \(co 2018-2026 Sergey Bugaev. +Copyright \(co 2019 Sergey Bugaev. License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. diff --git a/meson.build b/meson.build index 3109a50..6414a6f 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project('wl-clipboard', 'c', - version: '2.3.0', - license: 'GPL-3.0-or-later', - meson_version: '>= 0.47.0', + version: '2.0.0-beta', + license: 'GPL3+', + meson_version: '>= 0.44.0', default_options: 'c_std=gnu99' ) diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index b6e621c..0000000 --- a/meson_options.txt +++ /dev/null @@ -1,13 +0,0 @@ -option('protocols', - type: 'feature', - value: 'enabled') -option('zshcompletiondir', - type: 'string', - value: '', - description: 'Directory for zsh completions. Set "no" to disable.' -) -option('fishcompletiondir', - type: 'string', - value: '', - description: 'Directory for fish completions. Set "no" to disable.' -) diff --git a/src/includes/selection-protocols.h b/src/includes/selection-protocols.h index f01070b..32e74a7 100644 --- a/src/includes/selection-protocols.h +++ b/src/includes/selection-protocols.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,8 +35,4 @@ # include "wlr-data-control.h" #endif -#ifdef HAVE_EXT_DATA_CONTROL -# include "ext-data-control.h" -#endif - #endif /* INCLUDES_SELECTION_PROTOCOLS_H */ diff --git a/src/includes/shell-protocols.h b/src/includes/shell-protocols.h index 5d700d1..feb39f5 100644 --- a/src/includes/shell-protocols.h +++ b/src/includes/shell-protocols.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,13 +27,4 @@ # include "xdg-shell.h" #endif -#ifdef HAVE_GTK_SHELL -# include "gtk-shell.h" -#endif - -/* Not strictly speaking a shell */ -#ifdef HAVE_XDG_ACTIVATION -# include "xdg-activation.h" -#endif - #endif /* INCLUDES_SHELL_PROTOCOLS_H */ diff --git a/src/meson.build b/src/meson.build index e3b9bcf..45c2f67 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,25 @@ -wayland = dependency( - 'wayland-client', - default_options: ['tests=false', 'documentation=false', 'dtd_validation=false'] -) +wayland = dependency('wayland-client') + +wayland_scanner = find_program('wayland-scanner', required: false, native: true) +wayland_protocols = dependency('wayland-protocols', version: '>= 1.12', required: false) + +if wayland_scanner.found() + have_xdg_shell = wayland_protocols.found() + have_wp_primary_selection = wayland_protocols.found() and wayland_protocols.version().version_compare('>= 1.17') + # these are bundled + have_gtk_primary_selection = true + have_wlr_data_control = true + + if wayland.version().version_compare('>= 1.15') + scanner_code_command = 'private-code' + else + scanner_code_command = 'code' + endif +else + have_xdg_shell = false + have_gtk_primary_selection = false + have_wlr_data_control = false +endif cc = meson.get_compiler('c') have_memfd = cc.has_header_symbol('sys/syscall.h', 'SYS_memfd_create') @@ -9,65 +27,118 @@ have_shm_anon = cc.has_header_symbol('sys/mman.h', 'SHM_ANON') conf_data = configuration_data() +conf_data.set('PROJECT_VERSION', '"@0@"'.format(meson.project_version())) +conf_data.set('HAVE_XDG_SHELL', have_xdg_shell) +conf_data.set('HAVE_WP_PRIMARY_SELECTION', have_wp_primary_selection) +conf_data.set('HAVE_GTK_PRIMARY_SELECTION', have_gtk_primary_selection) +conf_data.set('HAVE_WLR_DATA_CONTROL', have_wlr_data_control) + conf_data.set('HAVE_MEMFD', have_memfd) conf_data.set('HAVE_SHM_ANON', have_shm_anon) -subdir('protocol') - configure_file(output: 'config.h', configuration: conf_data) +if wayland_protocols.found() + protocols_path = wayland_protocols.get_pkgconfig_variable('pkgdatadir') +endif + +protocols = [] + +if not have_xdg_shell + warning('Building without xdg-shell support') +else + xdg_shell_xml = join_paths(protocols_path, 'stable', 'xdg-shell', 'xdg-shell.xml') + protocols += [['xdg-shell', xdg_shell_xml]] +endif + +if have_wp_primary_selection + wp_primary_selection_xml = join_paths(protocols_path, 'unstable', 'primary-selection', 'primary-selection-unstable-v1.xml') + protocols += [['wp-primary-selection', wp_primary_selection_xml]] +endif + +if not have_gtk_primary_selection + warning('Building without primary selection support') +else + gtk_primary_selection_xml = join_paths('protocol', 'gtk-primary-selection.xml') + protocols += [['gtk-primary-selection', gtk_primary_selection_xml]] +endif + +if have_wlr_data_control + wlr_data_control_xml = join_paths('protocol', 'wlr-data-control-unstable-v1.xml') + protocols += [['wlr-data-control', wlr_data_control_xml]] +endif + +protocol_deps = [] +protocol_headers = [] + +foreach protocol : protocols + name = protocol[0] + xml = protocol[1] + header = custom_target(name + ' client header', + input: xml, output: name + '.h', + command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'] + ) + impl = custom_target(name + ' code', + input: xml, output: name + '.c', + command: [wayland_scanner, scanner_code_command, '@INPUT@', '@OUTPUT@'] + ) + protocol_headers += header + lib = static_library(name, impl, header, dependencies: wayland) + protocol_deps += lib +endforeach + lib = static_library( 'wl-clipboard', - protocol_headers, + [ + protocol_headers, - 'includes/shell-protocols.h', - 'includes/selection-protocols.h', + 'includes/shell-protocols.h', + 'includes/selection-protocols.h', - 'util/string.h', - 'util/string.c', - 'util/files.h', - 'util/files.c', - 'util/misc.h', - 'util/misc.c', + 'util/string.h', + 'util/string.c', + 'util/files.h', + 'util/files.c', + 'util/misc.h', + 'util/misc.c', - 'types/source.h', - 'types/source.c', - 'types/offer.h', - 'types/offer.c', - 'types/device.h', - 'types/device.c', - 'types/device-manager.h', - 'types/device-manager.c', - 'types/keyboard.h', - 'types/keyboard.c', - 'types/seat.h', - 'types/seat.c', - 'types/shell.h', - 'types/shell.c', - 'types/shell-surface.h', - 'types/shell-surface.c', - 'types/popup-surface.h', - 'types/popup-surface.c', - 'types/registry.h', - 'types/registry.c', - 'types/copy-action.h', - 'types/copy-action.c', + 'types/source.h', + 'types/source.c', + 'types/offer.h', + 'types/offer.c', + 'types/device.h', + 'types/device.c', + 'types/device-manager.h', + 'types/device-manager.c', + 'types/keyboard.h', + 'types/keyboard.c', + 'types/seat.h', + 'types/seat.c', + 'types/shell.h', + 'types/shell.c', + 'types/shell-surface.h', + 'types/shell-surface.c', + 'types/popup-surface.h', + 'types/popup-surface.c', + 'types/registry.h', + 'types/registry.c', + 'types/copy-action.h', + 'types/copy-action.c', + ], dependencies: wayland, link_with: protocol_deps ) executable( 'wl-copy', - 'wl-copy.c', - protocol_headers, + ['wl-copy.c', protocol_headers], dependencies: wayland, link_with: lib, install: true ) executable( 'wl-paste', - 'wl-paste.c', - protocol_headers, + ['wl-paste.c', protocol_headers], dependencies: wayland, link_with: lib, install: true diff --git a/src/protocol/gtk-shell.xml b/src/protocol/gtk-shell.xml deleted file mode 100644 index a8d51c6..0000000 --- a/src/protocol/gtk-shell.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - gtk_shell is a protocol extension providing additional features for - clients implementing it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/protocol/meson.build b/src/protocol/meson.build deleted file mode 100644 index b63218b..0000000 --- a/src/protocol/meson.build +++ /dev/null @@ -1,111 +0,0 @@ -protocols_opt = get_option('protocols') -wayland_scanner = find_program('wayland-scanner', required: protocols_opt, native: true) -wayland_protocols = dependency( - 'wayland-protocols', - version: '>= 1.12', - required: protocols_opt, - default_options: ['tests=false'] -) - -if wayland_scanner.found() - have_xdg_shell = wayland_protocols.found() - have_wp_primary_selection = wayland_protocols.found() and wayland_protocols.version().version_compare('>= 1.17') - have_xdg_activation = wayland_protocols.found() and wayland_protocols.version().version_compare('>= 1.21') - # these are bundled - have_gtk_primary_selection = true - have_wlr_data_control = true - have_ext_data_control = wayland_protocols.found() and wayland_protocols.version().version_compare('>= 1.39') - have_gtk_shell = true - - if wayland.version().version_compare('>= 1.15') - scanner_code_command = 'private-code' - else - scanner_code_command = 'code' - endif -else - have_xdg_shell = false - have_wp_primary_selection = false - have_xdg_activation = false - have_gtk_primary_selection = false - have_wlr_data_control = false - have_ext_data_control = false - have_gtk_shell = false -endif - -conf_data.set('PROJECT_VERSION', '"@0@"'.format(meson.project_version())) -conf_data.set('HAVE_XDG_SHELL', have_xdg_shell) -conf_data.set('HAVE_WP_PRIMARY_SELECTION', have_wp_primary_selection) -conf_data.set('HAVE_GTK_PRIMARY_SELECTION', have_gtk_primary_selection) -conf_data.set('HAVE_WLR_DATA_CONTROL', have_wlr_data_control) -conf_data.set('HAVE_EXT_DATA_CONTROL', have_ext_data_control) -conf_data.set('HAVE_XDG_ACTIVATION', have_xdg_activation) -conf_data.set('HAVE_GTK_SHELL', have_gtk_shell) - -if wayland_protocols.found() - if meson.version().version_compare('>= 0.58') - protocols_path = wayland_protocols.get_variable('pkgdatadir') - else - protocols_path = wayland_protocols.get_pkgconfig_variable('pkgdatadir') - endif -endif - -protocols = [] - -if not have_xdg_shell - warning('Building without xdg-shell support, wl-clipboard will be unable to work on some compositors') -else - xdg_shell_xml = join_paths(protocols_path, 'stable', 'xdg-shell', 'xdg-shell.xml') - protocols += [['xdg-shell', xdg_shell_xml]] -endif - -if have_wp_primary_selection - wp_primary_selection_xml = join_paths(protocols_path, 'unstable', 'primary-selection', 'primary-selection-unstable-v1.xml') - protocols += [['wp-primary-selection', wp_primary_selection_xml]] -endif - -if not have_gtk_primary_selection - warning('Building without primary selection support') -else - gtk_primary_selection_xml = 'gtk-primary-selection.xml' - protocols += [['gtk-primary-selection', gtk_primary_selection_xml]] -endif - -if have_wlr_data_control - wlr_data_control_xml = 'wlr-data-control-unstable-v1.xml' - protocols += [['wlr-data-control', wlr_data_control_xml]] -endif - -if have_ext_data_control - ext_data_control_xml = join_paths(protocols_path, 'staging', 'ext-data-control', 'ext-data-control-v1.xml') - protocols += [['ext-data-control', ext_data_control_xml]] -endif - -if have_xdg_activation - xdg_activation_xml = join_paths(protocols_path, 'staging', 'xdg-activation', 'xdg-activation-v1.xml') - protocols += [['xdg-activation', xdg_activation_xml]] -endif - -if have_gtk_shell - gtk_shell_xml = 'gtk-shell.xml' - protocols += [['gtk-shell', gtk_shell_xml]] -endif - - -protocol_deps = [] -protocol_headers = [] - -foreach protocol : protocols - name = protocol[0] - xml = protocol[1] - header = custom_target(name + ' client header', - input: xml, output: name + '.h', - command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'] - ) - impl = custom_target(name + ' code', - input: xml, output: name + '.c', - command: [wayland_scanner, scanner_code_command, '@INPUT@', '@OUTPUT@'] - ) - protocol_headers += header - lib = static_library(name, impl, header, dependencies: wayland) - protocol_deps += lib -endforeach diff --git a/src/types/copy-action.c b/src/types/copy-action.c index 79b0b0a..5ef9ea1 100644 --- a/src/types/copy-action.c +++ b/src/types/copy-action.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,24 +30,17 @@ #include #include #include -#include static void do_set_selection(struct copy_action *self, uint32_t serial) { /* Set the selection and make sure it reaches * the display before we do anything else, * such as destroying the surface or exiting. - * Make sure to unset the callback to prevent - * reentrancy issues. */ - if (self->popup_surface != NULL) { - self->popup_surface->on_focus = NULL; - self->popup_surface->data = NULL; - } device_set_selection(self->device, self->source, serial, self->primary); wl_display_roundtrip(self->device->wl_display); /* Now, if we have used a popup surface, destroy it */ - if (self->popup_surface != NULL) { + if (self->device->needs_popup_surface) { popup_surface_destroy(self->popup_surface); self->popup_surface = NULL; } @@ -69,24 +62,10 @@ static void on_focus( static void do_send(struct source *source, const char *mime_type, int fd) { struct copy_action *self = source->data; - /* Unset O_NONBLOCK */ + /* Unset O_NONBLOCK */ fcntl(fd, F_SETFL, 0); - if (!strcmp(mime_type, x_kde_password_manager_hint)) { - /* We always respond to x-kde-passwordManagerHint, - * even though we only offer it when --sensitive - * is set. - */ - const char *data = self->sensitive ? "secret" : "public"; - write(fd, data, strlen(data)); - close(fd); - /* This does not count as pasting, so don't invoke - * our pasted_callback, just return. - */ - return; - } - - if (self->fd_to_copy_from != -1) { + if (self->file_to_copy != NULL) { /* Copy the file to the given file descriptor * by spawning an appropriate cat process. */ @@ -97,13 +76,9 @@ static void do_send(struct source *source, const char *mime_type, int fd) { return; } if (pid == 0) { - dup2(self->fd_to_copy_from, STDIN_FILENO); - close(self->fd_to_copy_from); dup2(fd, STDOUT_FILENO); close(fd); - signal(SIGHUP, SIG_DFL); - signal(SIGPIPE, SIG_DFL); - execlp("cat", "cat", NULL); + execlp("cat", "cat", self->file_to_copy, NULL); perror("exec cat"); exit(1); } @@ -115,12 +90,7 @@ static void do_send(struct source *source, const char *mime_type, int fd) { * should switch to an asynchronous child waiting scheme * instead. */ - waitpid(pid, NULL, 0); - /* Seek back to the beginning of the file */ - off_t rc = lseek(self->fd_to_copy_from, 0, SEEK_SET); - if (rc < 0) { - perror("lseek"); - } + wait(NULL); } else { /* We'll perform the copy ourselves */ FILE *f = fdopen(fd, "w"); diff --git a/src/types/copy-action.h b/src/types/copy-action.h index 6c92e9a..c0a1290 100644 --- a/src/types/copy-action.h +++ b/src/types/copy-action.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +33,6 @@ struct copy_action { struct source *source; struct popup_surface *popup_surface; int primary; - int sensitive; void (*did_set_selection_callback)(struct copy_action *self); void (*pasted_callback)(struct copy_action *self); @@ -41,9 +40,8 @@ struct copy_action { /* Exactly one of these fields must be non-null if the source * is non-null, otherwise all these fields must be null. - * The null value for fd_to_copy_from is -1. */ - int fd_to_copy_from; + const char *file_to_copy; argv_t argv_to_copy; struct { const char *ptr; diff --git a/src/types/device-manager.c b/src/types/device-manager.c index 55e7aa7..bd6e04e 100644 --- a/src/types/device-manager.c +++ b/src/types/device-manager.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -138,23 +138,3 @@ GET_DEVICE( INIT(zwlr_data_control_manager_v1) #endif /* HAVE_WLR_DATA_CONTROL */ - -/* ext-data-control implementation */ - -#ifdef HAVE_EXT_DATA_CONTROL - -CREATE_SOURCE( - ext_data_control_manager_v1, - ext_data_control_source_v1, - create_data_source -) - -GET_DEVICE( - ext_data_control_manager_v1, - ext_data_control_device_v1, - get_data_device -) - -INIT(ext_data_control_manager_v1) - -#endif /* HAVE_EXT_DATA_CONTROL */ diff --git a/src/types/device-manager.h b/src/types/device-manager.h index 8629a57..bb7e88d 100644 --- a/src/types/device-manager.h +++ b/src/types/device-manager.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,10 +69,4 @@ void device_manager_init_zwlr_data_control_manager_v1( ); #endif -#ifdef HAVE_EXT_DATA_CONTROL -void device_manager_init_ext_data_control_manager_v1( - struct device_manager *self -); -#endif - #endif /* TYPES_DEVICE_MANAGER_H */ diff --git a/src/types/device.c b/src/types/device.c index 6282c1f..16525a6 100644 --- a/src/types/device.c +++ b/src/types/device.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +25,6 @@ #include #include -enum TriState { - Unknown, - Yes, - No -}; - int device_supports_selection(struct device *self, int primary) { return self->supports_selection(self, primary); } @@ -47,10 +41,7 @@ void device_set_selection( /* Macros to reduce implementation boilerplate */ #define SUPPORTS_SELECTION(type, expr) \ -static int device_supports_selection_on_ ## type( \ - struct device *self, \ - int primary \ -) { \ +static int device_supports_selection_on_ ## type(struct device *self, int primary) { \ return expr; \ } @@ -201,6 +192,12 @@ INIT(zwp_primary_selection_device_v1, 1) #ifdef HAVE_WLR_DATA_CONTROL +enum TriState { + Unknown, + Yes, + No +}; + /* Whether wlr-data-control supports primary selection */ static enum TriState device_wlr_supports_primary_selection = Unknown; static int device_get_wlr_supports_selection(struct device *self, int primary) { @@ -272,80 +269,3 @@ zwlr_data_control_device_v1_listener = { INIT(zwlr_data_control_device_v1, 0) #endif /* HAVE_WLR_DATA_CONTROL */ - - -/* ext-data-control implementation */ - -#ifdef HAVE_EXT_DATA_CONTROL - -/* Whether ext-data-control supports primary selection */ -static enum TriState device_ext_supports_primary_selection = Unknown; -static int device_get_ext_supports_selection(struct device *self, int primary) { - if (!primary) { - return 1; - } - - if (device_ext_supports_primary_selection == Yes) { - return 1; - } else if (device_ext_supports_primary_selection == No) { - return 0; - } - - wl_display_roundtrip(self->wl_display); - - if (device_ext_supports_primary_selection == Yes) { - return 1; - } else { - device_ext_supports_primary_selection = No; - return 0; - } -} - -SUPPORTS_SELECTION( - ext_data_control_device_v1, - device_get_ext_supports_selection(self, primary) -) - -SET_SELECTION_IMPL(ext_data_control_device_v1, ext_data_control_source_v1, { - if (!primary) { - ext_data_control_device_v1_set_selection(device, source); - } else { - ext_data_control_device_v1_set_primary_selection(device, source); - } -}) - -DATA_OFFER_HANDLER(ext_data_control_device_v1, ext_data_control_offer_v1) - -SELECTION_HANDLER( - ext_data_control_device_v1, - ext_data_control_offer_v1, - selection, - 0 -) - -static void ext_data_control_device_v1_primary_selection_handler( - void *data, - struct ext_data_control_device_v1 *device, - struct ext_data_control_offer_v1 *offer_proxy -) { - device_ext_supports_primary_selection = Yes; - struct device *self = data; - struct offer *offer = NULL; - if (offer_proxy != NULL) { - offer = wl_proxy_get_user_data((struct wl_proxy *) offer_proxy); - } - if (self->selection_callback != NULL) { - self->selection_callback(offer, 1); - } -} - -static const struct ext_data_control_device_v1_listener -ext_data_control_device_v1_listener = { - .data_offer = ext_data_control_device_v1_data_offer_handler, - .selection = ext_data_control_device_v1_selection_handler, - .primary_selection = ext_data_control_device_v1_primary_selection_handler -}; - -INIT(ext_data_control_device_v1, 0) - -#endif /* HAVE_EXT_DATA_CONTROL */ diff --git a/src/types/device.h b/src/types/device.h index ad780e0..5f5e3fe 100644 --- a/src/types/device.h +++ b/src/types/device.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -71,8 +71,4 @@ void device_init_zwp_primary_selection_device_v1(struct device *self); void device_init_zwlr_data_control_device_v1(struct device *self); #endif -#ifdef HAVE_EXT_DATA_CONTROL -void device_init_ext_data_control_device_v1(struct device *self); -#endif - #endif /* TYPES_DEVICE_H */ diff --git a/src/types/keyboard.c b/src/types/keyboard.c index 12eb82f..99ca793 100644 --- a/src/types/keyboard.c +++ b/src/types/keyboard.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/keyboard.h b/src/types/keyboard.h index 4e95d85..e5f02d0 100644 --- a/src/types/keyboard.h +++ b/src/types/keyboard.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/offer.c b/src/types/offer.c index cf3c7ff..c21a562 100644 --- a/src/types/offer.c +++ b/src/types/offer.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -105,13 +105,3 @@ INIT(zwlr_data_control_offer_v1) #endif /* HAVE_WLR_DATA_CONTROL */ - -/* ext-data-control implementation */ - -#ifdef HAVE_EXT_DATA_CONTROL - -OFFER_HANDLER(ext_data_control_offer_v1) -LISTENER(ext_data_control_offer_v1) -INIT(ext_data_control_offer_v1) - -#endif /* HAVE_EXT_DATA_CONTROL */ diff --git a/src/types/offer.h b/src/types/offer.h index c8eaed1..800466b 100644 --- a/src/types/offer.h +++ b/src/types/offer.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,11 +37,12 @@ struct offer { #define offer_for_each_mime_type(offer, mime_type) \ for ( \ const char *mime_type = offer->offered_mime_types.data; \ - mime_type != (const char *) offer->offered_mime_types.data + \ - offer->offered_mime_types.size; \ + mime_type != offer->offered_mime_types.data + \ + offer->offered_mime_types.size; \ mime_type += strlen(mime_type) + 1 \ ) + void offer_receive(struct offer *self, const char *mime_type, int fd); void offer_destroy(struct offer *self); @@ -61,8 +62,4 @@ void offer_init_zwp_primary_selection_offer_v1(struct offer *self); void offer_init_zwlr_data_control_offer_v1(struct offer *self); #endif -#ifdef HAVE_EXT_DATA_CONTROL -void offer_init_ext_data_control_offer_v1(struct offer *self); -#endif - #endif /* TYPES_OFFER_H */ diff --git a/src/types/popup-surface.c b/src/types/popup-surface.c index b8eee53..1aad115 100644 --- a/src/types/popup-surface.c +++ b/src/types/popup-surface.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,7 @@ static void forward_on_focus( void popup_surface_init(struct popup_surface *self) { self->shell = registry_find_shell(self->registry); if (self->shell == NULL) { - complain_about_missing_shell(); + bail("Missing a shell"); } self->keyboard = seat_get_keyboard(self->seat); @@ -61,7 +61,7 @@ void popup_surface_init(struct popup_surface *self) { struct wl_compositor *wl_compositor = self->registry->wl_compositor; if (wl_compositor == NULL) { - complain_about_missing_global("wl_compositor"); + bail("Missing the compositor"); } self->wl_surface = wl_compositor_create_surface(wl_compositor); self->shell_surface = shell_create_shell_surface( @@ -69,22 +69,13 @@ void popup_surface_init(struct popup_surface *self) { self->wl_surface ); -#ifdef HAVE_GTK_SHELL - if (self->registry->gtk_shell1 != NULL) { - self->gtk_surface = gtk_shell1_get_gtk_surface( - self->registry->gtk_shell1, - self->wl_surface - ); - } -#endif - /* Signal that the surface is ready to be configured */ wl_surface_commit(self->wl_surface); wl_display_roundtrip(self->registry->wl_display); if (self->wl_surface == NULL) { /* It's possible that we were given focus - * (without ever committing a buffer) during + * (without ever commiting a buffer) during * the above roundtrip, in which case we have * already fired the callback and have likely * already destroyed the surface. No need to @@ -106,15 +97,12 @@ void popup_surface_init(struct popup_surface *self) { /* Open an anonymous file and write some zero bytes to it */ int fd = create_anonymous_file(); - int rc = ftruncate(fd, size); - if (rc < 0) { - perror("ftruncate"); - } + ftruncate(fd, size); /* Create a shared memory pool */ struct wl_shm *wl_shm = self->registry->wl_shm; if (wl_shm == NULL) { - complain_about_missing_global("wl_shm"); + bail("Missing the shm"); } struct wl_shm_pool *wl_shm_pool = wl_shm_create_pool(wl_shm, fd, size); @@ -134,32 +122,6 @@ void popup_surface_init(struct popup_surface *self) { wl_surface_attach(self->wl_surface, wl_buffer, 0, 0); wl_surface_damage(self->wl_surface, 0, 0, width, height); - - /* Ask the compositor nicely to give us focus */ -#ifdef HAVE_GTK_SHELL - if (self->gtk_surface != NULL) { - gtk_surface1_present(self->gtk_surface, 0); - } -#endif -#ifdef HAVE_XDG_ACTIVATION - if (self->registry->xdg_activation_v1 != NULL) { - /* See if someone was kind enough to leave - * some tokens for us in the environment. - */ - const char *token = getenv("XDG_ACTIVATION_TOKEN"); - if (token == NULL) { - token = getenv("DESKTOP_STARTUP_ID"); - } - if (token != NULL) { - xdg_activation_v1_activate( - self->registry->xdg_activation_v1, - token, - self->wl_surface - ); - } - } -#endif - wl_surface_commit(self->wl_surface); } @@ -173,21 +135,7 @@ void popup_surface_destroy(struct popup_surface *self) { self->keyboard->data = NULL; shell_surface_destroy(self->shell_surface); -#ifdef HAVE_GTK_SHELL - if (self->gtk_surface != NULL) { - if ( - gtk_surface1_get_version(self->gtk_surface) >= - GTK_SURFACE1_RELEASE_SINCE_VERSION - ) { - gtk_surface1_release(self->gtk_surface); - } else { - gtk_surface1_destroy(self->gtk_surface); - } - } -#endif wl_surface_destroy(self->wl_surface); - /* Let popup_surface_init() know we're already done */ - self->wl_surface = NULL; free(self->shell); if (self->should_free_self) { diff --git a/src/types/popup-surface.h b/src/types/popup-surface.h index e6148a7..8847519 100644 --- a/src/types/popup-surface.h +++ b/src/types/popup-surface.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,8 +19,6 @@ #ifndef TYPES_POPUP_SURFACE_H #define TYPES_POPUP_SURFACE_H -#include "includes/shell-protocols.h" - #include struct registry; @@ -42,10 +40,6 @@ struct popup_surface { struct wl_surface *wl_surface; struct keyboard *keyboard; int should_free_self; - -#ifdef HAVE_GTK_SHELL - struct gtk_surface1 *gtk_surface; -#endif }; void popup_surface_init(struct popup_surface *self); diff --git a/src/types/registry.c b/src/types/registry.c index 7eeaec4..67c7fde 100644 --- a/src/types/registry.c +++ b/src/types/registry.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,14 +29,12 @@ #define BIND(interface_name, known_version) \ if (strcmp(interface, #interface_name) == 0) { \ - if (version >= (known_version)) { \ - self->interface_name = wl_registry_bind( \ - wl_registry, \ - name, \ - &interface_name ## _interface, \ - known_version \ - ); \ - } \ + self->interface_name = wl_registry_bind( \ + wl_registry, \ + name, \ + &interface_name ## _interface, \ + known_version \ + ); \ } static void wl_registry_global_handler( @@ -51,10 +49,6 @@ static void wl_registry_global_handler( BIND(wl_compositor, 2) BIND(wl_shm, 1) -#ifdef HAVE_XDG_ACTIVATION - BIND(xdg_activation_v1, 1) -#endif - /* Shells */ BIND(wl_shell, 1) @@ -63,10 +57,6 @@ static void wl_registry_global_handler( BIND(xdg_wm_base, 1) #endif -#ifdef HAVE_GTK_SHELL - BIND(gtk_shell1, 4) -#endif - /* Device managers */ BIND(wl_data_device_manager, 1) @@ -83,11 +73,7 @@ static void wl_registry_global_handler( BIND(zwlr_data_control_manager_v1, version > 2 ? 2 : version) #endif -#ifdef HAVE_EXT_DATA_CONTROL - BIND(ext_data_control_manager_v1, 1) -#endif - - if (strcmp(interface, "wl_seat") == 0 && version >= 2) { + if (strcmp(interface, "wl_seat") == 0) { struct seat *seat = calloc(1, sizeof(struct seat)); seat->proxy = wl_registry_bind( wl_registry, @@ -153,15 +139,12 @@ struct device_manager *registry_find_device_manager( = calloc(1, sizeof(struct device_manager)); device_manager->wl_display = self->wl_display; - /* For regular selection, we just look at the three supported - * protocols. We prefer ext-data-control or wlr-data-control, - * as they don't require us to use the popup surface hack. + /* For regular selection, we just look at the two supported + * protocols. We prefer wlr-data-control, as it doesn't require + * us to use the popup surface hack. */ if (!primary) { -#ifdef HAVE_EXT_DATA_CONTROL - TRY(ext_data_control_manager_v1) -#endif #ifdef HAVE_WLR_DATA_CONTROL TRY(zwlr_data_control_manager_v1) #endif @@ -179,16 +162,8 @@ struct device_manager *registry_find_device_manager( * that if a compositor supports primary selection at all, then * if it supports wlr-data-control v2 it also supports primary * selection over wlr-data-control; which is only reasonable. - * - * The same goes for the newer ext-data-control, which has - * potential support for primary selection since v1, so no need - * for the version check there. */ -#ifdef HAVE_EXT_DATA_CONTROL - TRY(ext_data_control_manager_v1) -#endif - #ifdef HAVE_WLR_DATA_CONTROL if (self->zwlr_data_control_manager_v1 != NULL) { struct wl_proxy *proxy diff --git a/src/types/registry.h b/src/types/registry.h index 30a62b5..e52e427 100644 --- a/src/types/registry.h +++ b/src/types/registry.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,19 +40,12 @@ struct registry { struct wl_compositor *wl_compositor; struct wl_shm *wl_shm; -#ifdef HAVE_XDG_ACTIVATION - struct xdg_activation_v1 *xdg_activation_v1; -#endif - /* Shells */ struct wl_shell *wl_shell; #ifdef HAVE_XDG_SHELL struct xdg_wm_base *xdg_wm_base; #endif -#ifdef HAVE_GTK_SHELL - struct gtk_shell1 *gtk_shell1; -#endif /* Device managers */ @@ -69,10 +62,6 @@ struct registry { struct zwlr_data_control_manager_v1 *zwlr_data_control_manager_v1; #endif -#ifdef HAVE_EXT_DATA_CONTROL - struct ext_data_control_manager_v1 - *ext_data_control_manager_v1; -#endif }; void registry_init(struct registry *self); diff --git a/src/types/seat.c b/src/types/seat.c index 3d7e604..6e48450 100644 --- a/src/types/seat.c +++ b/src/types/seat.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/seat.h b/src/types/seat.h index edcbcd6..cd92073 100644 --- a/src/types/seat.h +++ b/src/types/seat.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/shell-surface.c b/src/types/shell-surface.c index f2b73ec..ba7e61b 100644 --- a/src/types/shell-surface.c +++ b/src/types/shell-surface.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,7 +67,6 @@ void shell_surface_init_wl_shell_surface(struct shell_surface *self) { wl_shell_surface_add_listener(proxy, &wl_shell_surface_listener, self); wl_shell_surface_set_toplevel(proxy); wl_shell_surface_set_title(proxy, "wl-clipboard"); - wl_shell_surface_set_class(proxy, "io.github.bugaevc.wl-clipboard"); self->do_destroy = destroy_wl_shell_surface; } @@ -120,7 +119,6 @@ void shell_surface_init_xdg_surface(struct shell_surface *self) { self->proxy2 = (struct wl_proxy *) toplevel; xdg_toplevel_add_listener(toplevel, &xdg_toplevel_listener, self); xdg_toplevel_set_title(toplevel, "wl-clipboard"); - xdg_toplevel_set_app_id(toplevel, "io.github.bugaevc.wl-clipboard"); self->do_destroy = destroy_xdg_surface; } diff --git a/src/types/shell-surface.h b/src/types/shell-surface.h index fe70baf..d888553 100644 --- a/src/types/shell-surface.h +++ b/src/types/shell-surface.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/shell.c b/src/types/shell.c index 2a57f9f..36d192a 100644 --- a/src/types/shell.c +++ b/src/types/shell.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/shell.h b/src/types/shell.h index 5c8c2dd..9b866eb 100644 --- a/src/types/shell.h +++ b/src/types/shell.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/types/source.c b/src/types/source.c index 78f00ae..a59110d 100644 --- a/src/types/source.c +++ b/src/types/source.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -127,14 +127,3 @@ INIT(zwlr_data_control_source_v1) #endif /* HAVE_WLR_DATA_CONTROL */ - -/* ext-data-control implementation */ - -#ifdef HAVE_EXT_DATA_CONTROL - -SEND_HANDLER(ext_data_control_source_v1) -CANCELLED_HANDLER(ext_data_control_source_v1) -LISTENER(ext_data_control_source_v1) -INIT(ext_data_control_source_v1) - -#endif /* HAVE_EXT_DATA_CONTROL */ diff --git a/src/types/source.h b/src/types/source.h index a29d816..b471fe7 100644 --- a/src/types/source.h +++ b/src/types/source.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,8 +52,4 @@ void source_init_zwp_primary_selection_source_v1(struct source *self); void source_init_zwlr_data_control_source_v1(struct source *self); #endif -#ifdef HAVE_EXT_DATA_CONTROL -void source_init_ext_data_control_source_v1(struct source *self); -#endif - #endif /* TYPES_SOURCE_H */ diff --git a/src/util/files.c b/src/util/files.c index 078c051..14a3091 100644 --- a/src/util/files.c +++ b/src/util/files.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,15 +27,12 @@ #include #include #include -#include -#include +#include // open #include // open #include // open #include // exit #include // basename #include -#include -#include #ifdef HAVE_MEMFD # include // syscall, SYS_memfd_create @@ -44,42 +41,6 @@ # include // shm_open, SHM_ANON #endif -#include // wl_display_get_fd - - -void complain_about_closed_stdio(struct wl_display *wl_display) { - const char *message = "wl-clipboard has been launched with a closed" - " standard file descriptor. This is a bug in the software that" - " has launched wl-clipboard. Aborting."; - - /* See if we can write to stderr */ - if (wl_display_get_fd(wl_display) < STDERR_FILENO) { - int rc = fcntl(STDERR_FILENO, F_GETFL); - if (rc > 0) { - rc &= O_ACCMODE; - if (rc == O_WRONLY || rc == O_RDWR) { - /* Yes, we can! */ - fprintf(stderr, "%s\n", message); - fflush(stderr); - abort(); - } - } - } - - /* Maybe there is a tty we could write to? */ - FILE *tty = fopen("/dev/tty", "w"); - if (tty != NULL) { - fprintf(tty, "%s\n", message); - fflush(tty); - abort(); - } - - /* As a last resort, try syslog */ - openlog("wl-clipboard", LOG_CONS | LOG_PID, LOG_USER); - syslog(LOG_ERR, "%s", message); - closelog(); - abort(); -} int create_anonymous_file() { int res; @@ -162,22 +123,15 @@ char *infer_mime_type_from_contents(const char *file_path) { close(pipefd[0]); close(pipefd[1]); int devnull = open("/dev/null", O_RDONLY); - if (devnull >= 0) { - dup2(devnull, STDIN_FILENO); - close(devnull); - } else { - /* If we cannot open /dev/null, just close stdin */ - close(STDIN_FILENO); - } - signal(SIGHUP, SIG_DFL); - signal(SIGPIPE, SIG_DFL); + dup2(devnull, STDIN_FILENO); + close(devnull); execlp("xdg-mime", "xdg-mime", "query", "filetype", file_path, NULL); exit(1); } close(pipefd[1]); int wstatus; - waitpid(pid, &wstatus, 0); + wait(&wstatus); /* See if that worked */ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { @@ -187,15 +141,11 @@ char *infer_mime_type_from_contents(const char *file_path) { /* Read the result */ char *res = malloc(256); - ssize_t len = read(pipefd[0], res, 256); - close(pipefd[0]); - if (len <= 0) { - free(res); - return NULL; - } + size_t len = read(pipefd[0], res, 256); /* Trim the newline */ len--; res[len] = 0; + close(pipefd[0]); if (str_has_prefix(res, "inode/")) { free(res); @@ -205,8 +155,9 @@ char *infer_mime_type_from_contents(const char *file_path) { return res; } -static char *search_mime_dot_types_for_ext(const char *ext) { - if (ext == NULL) { +char *infer_mime_type_from_name(const char *file_path) { + const char *actual_ext = get_file_extension(file_path); + if (actual_ext == NULL) { return NULL; } @@ -219,7 +170,7 @@ static char *search_mime_dot_types_for_ext(const char *ext) { } for (char line[200]; fgets(line, sizeof(line), f) != NULL;) { - /* Skip comments and blank lines */ + /* Skip comments and black lines */ if (line[0] == '#' || line[0] == '\n') { continue; } @@ -229,12 +180,11 @@ static char *search_mime_dot_types_for_ext(const char *ext) { int consumed; if (sscanf(line, "%199s%n", mime_type, &consumed) != 1) { /* A malformed line, perhaps? */ - fprintf(stderr, "malformed mime.types line: %s\n", line); continue; } char *lineptr = line + consumed; - for (char ext_pattern[200]; sscanf(lineptr, "%199s%n", ext_pattern, &consumed) == 1;) { - if (strcmp(ext_pattern, ext) == 0) { + for (char ext[200]; sscanf(lineptr, "%199s%n", ext, &consumed) == 1;) { + if (strcmp(ext, actual_ext) == 0) { fclose(f); return strdup(mime_type); } @@ -245,86 +195,28 @@ static char *search_mime_dot_types_for_ext(const char *ext) { return NULL; } -static char *search_shared_mime_info_globs_for_filename(const char *filename) { - FILE *f = fopen("/usr/share/mime/globs2", "r"); - if (f == NULL) { - f = fopen("/usr/local/share/mime/globs2", "r"); - } - if (f == NULL) { - return NULL; - } - - for (char line[200]; fgets(line, sizeof(line), f) != NULL;) { - /* Skip comments and blank lines */ - if (line[0] == '#' || line[0] == '\n') { - continue; - } - - /* Each line consists of colon-separated - * weight, mime type, and glob pattern. - * We ignore the weight. - */ - char mime_type[200]; - char filename_glob[200]; - if (sscanf(line, "%*d:%199[^:]:%199s\n", mime_type, filename_glob) != 2) { - /* A malformed line, perhaps? */ - fprintf(stderr, "malformed globs2 line: %s\n", line); - continue; - } - if (fnmatch(filename_glob, filename, 0) == 0) { - fclose(f); - return strdup(mime_type); - } - } - fclose(f); - return NULL; -} - -char *infer_mime_type_from_name(const char *file_path) { - const char *ext = get_file_extension(file_path); - char *file_path_dup = strdup(file_path); - const char *filename = basename(file_path_dup); - char *mime_type = search_shared_mime_info_globs_for_filename(filename); - if (!mime_type) { - mime_type = search_mime_dot_types_for_ext(ext); - } - free(file_path_dup); - return mime_type; -} - /* Returns the name of a new file */ char *dump_stdin_into_a_temp_file() { + /* Create a temp directory to host out file */ + char dirpath[] = "/tmp/wl-copy-buffer-XXXXXX"; + if (mkdtemp(dirpath) != dirpath) { + perror("mkdtemp"); + exit(1); + } + /* Pick a name for the file we'll be * creating inside that directory. We - * try to preserve the original name for + * try to preserve the origial name for * the mime type inference to work. */ char *original_path = path_for_fd(STDIN_FILENO); char *name = original_path != NULL ? basename(original_path) : "stdin"; - /* Create a temp directory to host out file */ - const char *tmpdir = getenv("TMPDIR"); - if (tmpdir == NULL) { - tmpdir = "/tmp"; - } - size_t tmpdir_len = strlen(tmpdir); - static const char dir_template[] = "wl-copy-buffer-XXXXXX"; - char *path = malloc( - tmpdir_len + 1 + strlen(dir_template) + 1 + strlen(name) + 1 - ); - memcpy(path, tmpdir, tmpdir_len); - path[tmpdir_len] = '/'; - memcpy(path + tmpdir_len + 1, dir_template, strlen(dir_template)); - size_t prefix_len = tmpdir_len + 1 + strlen(dir_template); - path[prefix_len] = 0; - - if (mkdtemp(path) != path) { - perror("mkdtemp"); - exit(1); - } - - path[prefix_len] = '/'; - strcpy(path + prefix_len + 1, name); + /* Construct the path */ + char *res_path = malloc(strlen(dirpath) + 1 + strlen(name) + 1); + memcpy(res_path, dirpath, sizeof(dirpath)); + res_path[sizeof(dirpath) - 1] = '/'; + strcpy(res_path + sizeof(dirpath), name); /* Spawn cat to perform the copy */ pid_t pid = fork(); @@ -333,25 +225,25 @@ char *dump_stdin_into_a_temp_file() { exit(1); } if (pid == 0) { - int fd = creat(path, S_IRUSR | S_IWUSR); + int fd = creat(res_path, S_IRUSR | S_IWUSR); if (fd < 0) { perror("creat"); exit(1); } dup2(fd, STDOUT_FILENO); close(fd); - signal(SIGHUP, SIG_DFL); - signal(SIGPIPE, SIG_DFL); execlp("cat", "cat", NULL); perror("exec cat"); exit(1); } int wstatus; - waitpid(pid, &wstatus, 0); - free(original_path); + wait(&wstatus); + if (original_path != NULL) { + free(original_path); + } if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { bail("Failed to copy the file"); } - return path; + return res_path; } diff --git a/src/util/files.h b/src/util/files.h index e39ca4f..2a2d4b6 100644 --- a/src/util/files.h +++ b/src/util/files.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,9 +19,6 @@ #ifndef UTIL_FILES_H #define UTIL_FILES_H -struct wl_display; -void complain_about_closed_stdio(struct wl_display *wl_display); - int create_anonymous_file(void); void trim_trailing_newline(const char *file_path); diff --git a/src/util/misc.c b/src/util/misc.c index 4edd822..e9f7671 100644 --- a/src/util/misc.c +++ b/src/util/misc.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,14 +20,11 @@ #include "util/misc.h" #include -#include -#include -#include void print_version_info() { printf( "wl-clipboard " PROJECT_VERSION "\n" - "Copyright (C) 2018-2026 Sergey Bugaev\n" + "Copyright (C) 2019 Sergey Bugaev\n" "License GPLv3+: GNU GPL version 3 or later" " .\n" "This is free software: you are free to change and redistribute it.\n" @@ -38,7 +35,7 @@ void print_version_info() { void complain_about_selection_support(int primary) { if (!primary) { /* We always expect to find at least wl_data_device_manager */ - complain_about_missing_global("wl_data_device_manager"); + bail("Missing a required global object"); } #if !defined(HAVE_WP_PRIMARY_SELECTION) && !defined(HAVE_GTK_PRIMARY_SELECTION) @@ -49,91 +46,14 @@ void complain_about_selection_support(int primary) { } void complain_about_watch_mode_support() { -#if defined(HAVE_WLR_DATA_CONTROL) || defined(HAVE_EXT_DATA_CONTROL) +#ifdef HAVE_WLR_DATA_CONTROL bail( - "Watch mode requires a compositor that supports" - " the data-control protocol" + "Watch mode requires a compositor that supports " + "wlroots data-control protocol" ); #else bail( - "wl-clipboard was built without support for" - " the data-control protocol" + "wl-clipboard was built without wlroots data-control protocol support" ); #endif } - -void complain_about_wayland_connection() { - int saved_errno = errno; - fprintf(stderr, "Failed to connect to a Wayland server"); - if (saved_errno != 0) { - fprintf(stderr, ": %s", strerror(saved_errno)); - } - fputc('\n', stderr); - - const char *display = getenv("WAYLAND_DISPLAY"); - const char *runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (display != NULL) { - fprintf(stderr, "Note: WAYLAND_DISPLAY is set to %s\n", display); - } else { - fprintf( - stderr, - "Note: WAYLAND_DISPLAY is unset" - " (falling back to wayland-0)\n" - ); - display = "wayland-0"; - } - if (runtime_dir != NULL) { - fprintf(stderr, "Note: XDG_RUNTIME_DIR is set to %s\n", runtime_dir); - } else { - fprintf(stderr, "Note: XDG_RUNTIME_DIR is unset\n"); - } - if (display[0] != '/' && runtime_dir != NULL) { - fprintf( - stderr, - "Please check whether %s/%s socket exists and is accessible.\n", - runtime_dir, - display - ); - } - exit(1); -} - -void complain_about_missing_seat(const char *seat_name) { - if (seat_name != NULL) { - fprintf(stderr, "No such seat: %s\n", seat_name); - } else { - complain_about_missing_global("seat"); - } - exit(1); -} - -void complain_about_missing_global(const char *global) { - fprintf( - stderr, - "The compositor does not seem to implement %s," - " which is required for wl-clipboard to work\n", - global - ); - exit(1); -} - -void complain_about_missing_shell() { -#ifndef HAVE_XDG_SHELL - fprintf( - stderr, - "wl-clipboard was built without xdg-shell support, and the compositor" - " does not seem to support any other Wayland shell.\nPlease rebuild" - " wl-clipboard with xdg-shell support.\n" - ); - exit(1); -#endif - - - fprintf( - stderr, - "The compositor does not seem to implement a Wayland shell," - " which is required for wl-clipboard to work\n" - ); - - exit(1); -} diff --git a/src/util/misc.h b/src/util/misc.h index 299a0a6..02c9984 100644 --- a/src/util/misc.h +++ b/src/util/misc.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,9 +28,5 @@ void print_version_info(void); void complain_about_selection_support(int primary); void complain_about_watch_mode_support(void); -void complain_about_wayland_connection(void); -void complain_about_missing_seat(const char *seat_name); -void complain_about_missing_global(const char *global); -void complain_about_missing_shell(void); #endif /* UTIL_MISC_H */ diff --git a/src/util/string.c b/src/util/string.c index 9482bf9..f39db31 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,9 +36,7 @@ int mime_type_is_text(const char *mime_type) { = strstr(mime_type, "json") != NULL || str_has_suffix(mime_type, "script") || str_has_suffix(mime_type, "xml") - || str_has_suffix(mime_type, "yaml") - || str_has_suffix(mime_type, "csv") - || str_has_suffix(mime_type, "ini"); + || str_has_suffix(mime_type, "yaml"); /* Special-case PGP and SSH keys. * A public SSH key is typically stored diff --git a/src/util/string.h b/src/util/string.h index e007f2e..239cf58 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,6 @@ #define text_plain "text/plain" #define text_plain_utf8 "text/plain;charset=utf-8" -#define x_kde_password_manager_hint "x-kde-passwordManagerHint" typedef char * const *argv_t; diff --git a/src/wl-copy.c b/src/wl-copy.c index 660fb80..e474e94 100644 --- a/src/wl-copy.c +++ b/src/wl-copy.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ #include "types/device-manager.h" #include "types/registry.h" #include "types/popup-surface.h" -#include "types/offer.h" #include "util/files.h" #include "util/string.h" @@ -31,10 +30,8 @@ #include #include #include -#include // open #include #include -#include static struct { int stay_in_foreground; @@ -43,7 +40,6 @@ static struct { int trim_newline; int paste_once; int primary; - int sensitive; const char *seat_name; } options; @@ -56,29 +52,8 @@ static void did_set_selection_callback(struct copy_action *copy_action) { /* Move to background. * We fork our process and leave the * child running in the background, - * while exiting in the parent. We also - * replace stdin/stdout with /dev/null - * so the stdout file descriptor isn't - * kept alive, and chdir to the root, to - * prevent blocking file systems from - * being unmounted. + * while exiting in the parent. */ - int devnull = open("/dev/null", O_RDWR); - if (devnull >= 0) { - dup2(devnull, STDOUT_FILENO); - dup2(devnull, STDIN_FILENO); - close(devnull); - } else { - /* If we cannot open /dev/null, - * just close stdin/stdout. - */ - close(STDIN_FILENO); - close(STDOUT_FILENO); - } - if (chdir("/") < 0) { - perror("chdir /"); - } - signal(SIGHUP, SIG_IGN); pid_t pid = fork(); if (pid < 0) { perror("fork"); @@ -90,20 +65,28 @@ static void did_set_selection_callback(struct copy_action *copy_action) { } } -static void cancelled_callback(struct copy_action *copy_action) { - exit(0); -} - -static void pasted_callback(struct copy_action *copy_action) { - if (options.paste_once) { +static void cleanup_and_exit(struct copy_action *copy_action) { + /* We're done copying! + * All that's left to do now is to + * clean up after ourselves and exit.*/ + char *temp_file = (char *) copy_action->file_to_copy; + if (temp_file != NULL) { + /* Clean up our temporary file */ + execlp("rm", "rm", "-r", dirname(temp_file), NULL); + perror("exec rm"); + exit(1); + } else { exit(0); } } -static void selection_callback(struct offer *offer, int primary) { - /* We're not interested */ - if (offer != NULL) { - offer_destroy(offer); +static void cancelled_callback(struct copy_action *copy_action) { + cleanup_and_exit(copy_action); +} + +static void pasted_callback(struct copy_action *copy_action) { + if (options.paste_once) { + cleanup_and_exit(copy_action); } } @@ -117,12 +100,11 @@ static void print_usage(FILE *f, const char *argv0) { "Options:\n" "\t-o, --paste-once\tOnly serve one paste request and then exit.\n" "\t-f, --foreground\tStay in the foreground instead of forking.\n" - "\t-c, --clear\t\tInstead of copying, clear the clipboard.\n" + "\t-c, --clear\t\tInstead of copying anything, clear the clipboard.\n" "\t-p, --primary\t\tUse the \"primary\" clipboard.\n" "\t-n, --trim-newline\tDo not copy the trailing newline character.\n" "\t-t, --type mime/type\t" "Override the inferred MIME type for the content.\n" - "\t --sensitive\t\tHint that the content is sensitive.\n" "\t-s, --seat seat-name\t" "Pick the seat to work with.\n" "\t-v, --version\t\tDisplay version info.\n" @@ -149,7 +131,6 @@ static void parse_options(int argc, argv_t argv) { {"foreground", no_argument, 0, 'f'}, {"clear", no_argument, 0, 'c'}, {"type", required_argument, 0, 't'}, - {"sensitive", no_argument, 0, 'S'}, {"seat", required_argument, 0, 's'}, {0, 0, 0, 0} }; @@ -188,9 +169,6 @@ static void parse_options(int argc, argv_t argv) { case 't': options.mime_type = strdup(optarg); break; - case 'S': - options.sensitive = 1; - break; case 's': options.seat_name = strdup(optarg); break; @@ -205,20 +183,9 @@ static void parse_options(int argc, argv_t argv) { int main(int argc, argv_t argv) { parse_options(argc, argv); - /* Ignore SIGPIPE. - * We don't really output anything - * to our stdout, yet we don't want - * to get killed when writing clipboard - * contents to a closed pipe. - */ - signal(SIGPIPE, SIG_IGN); - struct wl_display *wl_display = wl_display_connect(NULL); if (wl_display == NULL) { - complain_about_wayland_connection(); - } - if (wl_display_get_fd(wl_display) <= STDERR_FILENO) { - complain_about_closed_stdio(wl_display); + bail("Failed to connect to a Wayland server"); } struct registry *registry = calloc(1, sizeof(struct registry)); @@ -230,7 +197,11 @@ int main(int argc, argv_t argv) { struct seat *seat = registry_find_seat(registry, options.seat_name); if (seat == NULL) { - complain_about_missing_seat(options.seat_name); + if (options.seat_name != NULL) { + bail("No such seat"); + } else { + bail("Missing a seat"); + } } /* Create the device */ @@ -241,7 +212,6 @@ int main(int argc, argv_t argv) { } struct device *device = device_manager_get_device(device_manager, seat); - device->selection_callback = selection_callback; if (!device_supports_selection(device, options.primary)) { complain_about_selection_support(options.primary); @@ -249,10 +219,8 @@ int main(int argc, argv_t argv) { /* Create and initialize the copy action */ struct copy_action *copy_action = calloc(1, sizeof(struct copy_action)); - copy_action->fd_to_copy_from = -1; copy_action->device = device; copy_action->primary = options.primary; - copy_action->sensitive = options.sensitive; if (!options.clear) { if (optind < argc) { @@ -273,28 +241,7 @@ int main(int argc, argv_t argv) { if (options.mime_type == NULL) { options.mime_type = infer_mime_type_from_contents(temp_file); } - copy_action->fd_to_copy_from = open( - temp_file, - O_RDONLY | O_CLOEXEC - ); - if (copy_action->fd_to_copy_from < 0) { - perror("Failed to open temp file"); - return 1; - } - /* Now, remove the temp file and its - * containing directory. We still keep - * access to the file through our open - * file descriptor. - */ - int rc = unlink(temp_file); - if (rc < 0) { - perror("Failed to unlink temp file"); - } - rc = rmdir(dirname(temp_file)); - if (rc < 0) { - perror("Failed to remove temp file directory"); - } - free(temp_file); + copy_action->file_to_copy = temp_file; } /* Create the source */ @@ -312,9 +259,6 @@ int main(int argc, argv_t argv) { } free(options.mime_type); options.mime_type = NULL; - if (options.sensitive) { - source_offer(copy_action->source, x_kde_password_manager_hint); - } } if (device->needs_popup_surface) { diff --git a/src/wl-paste.c b/src/wl-paste.c index 39b49fe..1c61974 100644 --- a/src/wl-paste.c +++ b/src/wl-paste.c @@ -1,6 +1,6 @@ /* wl-clipboard * - * Copyright © 2018-2026 Sergey Bugaev + * Copyright © 2019 Sergey Bugaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,8 +28,6 @@ #include #include -#include -#include #include #include #include @@ -53,7 +51,6 @@ struct types { int inferred_available; int plain_text_utf8_available; int plain_text_available; - int has_sensitive_hint; const char *having_explicit_as_prefix; const char *any_text; const char *any; @@ -61,7 +58,6 @@ struct types { static struct wl_display *wl_display = NULL; static struct popup_surface *popup_surface = NULL; -static int offer_received = 0; static struct types classify_offer_types(struct offer *offer) { struct types types = { 0 }; @@ -100,14 +96,6 @@ static struct types classify_offer_types(struct offer *offer) { ) { types.having_explicit_as_prefix = mime_type; } - if (strcmp(mime_type, x_kde_password_manager_hint) == 0) { - /* We should be checking if it contains - * the string "secret" as opposed to "public", - * but for now let's just use the presence - * of the type as an indication. - */ - types.has_sensitive_hint = 1; - } } return types; } @@ -183,84 +171,7 @@ static const char *mime_type_to_request(struct types types) { #undef try_any_text #undef try_any -static int run_paste_command( - int stdin_fd, - const char *clipboard_state, - const char *mime_type -) { - /* Spawn a cat to perform the copy. - * If watch mode is active, we spawn - * a custom command instead. - */ - pid_t pid = fork(); - if (pid < 0) { - perror("fork"); - close(stdin_fd); - return 0; - } - if (pid == 0) { - dup2(stdin_fd, STDIN_FILENO); - close(stdin_fd); - if (options.watch) { - if (clipboard_state != NULL) { - setenv("CLIPBOARD_STATE", clipboard_state, 1); - } - if (mime_type != NULL) { - setenv("CLIPBOARD_TYPE", mime_type, 1); - } - execvp(options.watch_command[0], options.watch_command); - fprintf( - stderr, - "Failed to spawn %s: %s", - options.watch_command[0], - strerror(errno) - ); - } else { - execlp("cat", "cat", NULL); - perror("exec cat"); - } - exit(1); - } - close(stdin_fd); - waitpid(pid, NULL, 0); - return 1; -} - -static void complain_no_suitable_type(const struct types *types) { - if (types->any == NULL) { - /* Report this the same way as - * there being no offer at all. - */ - bail("Nothing is copied"); - } - fprintf(stderr, "Clipboard content is not available as "); - if (options.explicit_type != NULL) { - fprintf(stderr, "requested type \"%s\"\n", options.explicit_type); - } else { - assert(options.inferred_type); - fprintf( - stderr, - "inferred output type \"%s\"\n", - options.inferred_type - ); - } - fprintf(stderr, "Use \"wl-paste --list-types\" to view available types."); - if (options.explicit_type == NULL) { - fprintf(stderr, " Use \"--type\" to explicitly specify a type."); - } - fputc('\n', stderr); - exit(1); -} - static void selection_callback(struct offer *offer, int primary) { - /* Ignore all but the first non-NULL offer. - * This could happen due to reentrancy, though - * we try to prevent it in other ways. - */ - if (offer_received && !options.watch) { - return; - } - /* Ignore events we're not interested in */ if (primary != options.primary) { if (offer != NULL) { @@ -270,20 +181,12 @@ static void selection_callback(struct offer *offer, int primary) { } if (offer == NULL) { - if (!options.watch) { - bail("Nothing is copied"); - } - int devnull = open("/dev/null", O_RDONLY | O_CLOEXEC); - if (devnull < 0) { - perror("open /dev/null"); + if (options.watch) { return; } - run_paste_command(devnull, "nil", NULL); - return; + bail("No selection"); } - offer_received = 1; - if (options.list_types) { offer_for_each_mime_type(offer, mime_type) { printf("%s\n", mime_type); @@ -299,7 +202,7 @@ static void selection_callback(struct offer *offer, int primary) { offer_destroy(offer); return; } - complain_no_suitable_type(&types); + bail("No suitable type of content copied"); } /* Never append a newline character to binary content */ @@ -327,28 +230,45 @@ static void selection_callback(struct offer *offer, int primary) { popup_surface_destroy(popup_surface); popup_surface = NULL; } - /* Make sure the receive request reaches - * the compositor before we block on reading. - * We call flush() instead of dispatch() to - * prevent reentrancy. - */ - wl_display_flush(wl_display); + wl_display_roundtrip(wl_display); - close(pipefd[1]); - const char *clipboard_state = "data"; - if (types.has_sensitive_hint) { - clipboard_state = "sensitive"; - } - rc = run_paste_command(pipefd[0], clipboard_state, mime_type); - if (!rc) { + /* Spawn a cat to perform the copy. + * If watch mode is active, we spawn + * a custom command instead. + */ + pid_t pid = fork(); + if (pid < 0) { + perror("fork"); if (options.watch) { /* Try to cope without exiting completely */ + close(pipefd[0]); + close(pipefd[1]); offer_destroy(offer); return; } exit(1); } - + if (pid == 0) { + dup2(pipefd[0], STDIN_FILENO); + close(pipefd[0]); + close(pipefd[1]); + if (options.watch) { + execvp(options.watch_command[0], options.watch_command); + fprintf( + stderr, + "Failed to spawn %s: %s", + options.watch_command[0], + strerror(errno) + ); + } else { + execlp("cat", "cat", NULL); + perror("exec cat"); + } + exit(1); + } + close(pipefd[0]); + close(pipefd[1]); + wait(NULL); if (!options.no_newline && !options.watch) { rc = write(STDOUT_FILENO, "\n", 1); if (rc != 1) { @@ -498,10 +418,7 @@ int main(int argc, argv_t argv) { wl_display = wl_display_connect(NULL); if (wl_display == NULL) { - complain_about_wayland_connection(); - } - if (wl_display_get_fd(wl_display) <= STDERR_FILENO) { - complain_about_closed_stdio(wl_display); + bail("Failed to connect to a Wayland server"); } struct registry *registry = calloc(1, sizeof(struct registry)); @@ -513,7 +430,11 @@ int main(int argc, argv_t argv) { struct seat *seat = registry_find_seat(registry, options.seat_name); if (seat == NULL) { - complain_about_missing_seat(options.seat_name); + if (options.seat_name != NULL) { + bail("No such seat"); + } else { + bail("Missing a seat"); + } } /* Create the device */ diff --git a/subprojects/expat.wrap b/subprojects/expat.wrap deleted file mode 100644 index bda9011..0000000 --- a/subprojects/expat.wrap +++ /dev/null @@ -1,13 +0,0 @@ -[wrap-file] -directory = expat-2.5.0 -source_url = https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.xz -source_filename = expat-2.5.0.tar.bz2 -source_hash = ef2420f0232c087801abf705e89ae65f6257df6b7931d37846a193ef2e8cdcbe -patch_filename = expat_2.5.0-3_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.5.0-3/get_patch -patch_hash = e30c8c32f79fd4563a86a5c9cfe419568c35b775077c2d1428170081129406b4 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/expat_2.5.0-3/expat-2.5.0.tar.bz2 -wrapdb_version = 2.5.0-3 - -[provide] -expat = expat_dep diff --git a/subprojects/libffi.wrap b/subprojects/libffi.wrap deleted file mode 100644 index 18baccc..0000000 --- a/subprojects/libffi.wrap +++ /dev/null @@ -1,13 +0,0 @@ -[wrap-file] -directory = libffi-3.5.2 -source_url = https://github.com/libffi/libffi/releases/download/v3.5.2/libffi-3.5.2.tar.gz -source_filename = libffi-3.5.2.tar.gz -source_hash = f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libffi_3.5.2-2/libffi-3.5.2.tar.gz -patch_filename = libffi_3.5.2-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/libffi_3.5.2-2/get_patch -patch_hash = 74ed624f74cd860be3bdf6d473b70ab88707bdf2f940191fbcb577e2a49a9710 -wrapdb_version = 3.5.2-2 - -[provide] -dependency_names = libffi diff --git a/subprojects/wayland-protocols.wrap b/subprojects/wayland-protocols.wrap deleted file mode 100644 index 71650c7..0000000 --- a/subprojects/wayland-protocols.wrap +++ /dev/null @@ -1,8 +0,0 @@ -[wrap-file] -directory = wayland-protocols-1.24 -source_url = https://wayland.freedesktop.org/releases/wayland-protocols-1.24.tar.xz -source_filename = wayland-protocols-1.24.tar.xz -source_hash = bff0d8cffeeceb35159d6f4aa6bab18c807b80642c9d50f66cba52ecf7338bc2 - -[provide] -wayland-protocols = wayland_protocols diff --git a/subprojects/wayland.wrap b/subprojects/wayland.wrap deleted file mode 100644 index e0991a2..0000000 --- a/subprojects/wayland.wrap +++ /dev/null @@ -1,9 +0,0 @@ -[wrap-file] -directory = wayland-1.22.0 -source_url = https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.22.0/downloads/wayland-1.22.0.tar.xz -source_filename = wayland-1.22.0.tar.xz -source_hash = 1540af1ea698a471c2d8e9d288332c7e0fd360c8f1d12936ebb7e7cbc2425842 - -[provide] -dependency_names = wayland-client, wayland-server, wayland-cursor, wayland-egl -program_names = wayland-scanner