Coverage Report

Created: 2025-06-12 07:21

/src/mpv/player/clipboard/clipboard.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * This file is part of mpv.
3
 *
4
 * mpv is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * mpv is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with mpv.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#include "clipboard.h"
19
20
#include "common/common.h"
21
#include "common/global.h"
22
#include "options/m_config.h"
23
#include "player/core.h"
24
25
struct clipboard_opts {
26
    bool monitor;
27
    struct m_obj_settings *backends;
28
};
29
30
// backend list
31
extern const struct clipboard_backend clipboard_backend_win32;
32
extern const struct clipboard_backend clipboard_backend_mac;
33
extern const struct clipboard_backend clipboard_backend_wayland;
34
extern const struct clipboard_backend clipboard_backend_vo;
35
36
static const struct clipboard_backend *const clipboard_backend_list[] = {
37
#if HAVE_WIN32_DESKTOP
38
    &clipboard_backend_win32,
39
#endif
40
#if HAVE_COCOA
41
    &clipboard_backend_mac,
42
#endif
43
#if HAVE_WAYLAND_PROTOCOLS_1_39
44
    &clipboard_backend_wayland,
45
#endif
46
    &clipboard_backend_vo,
47
};
48
49
static bool get_desc(struct m_obj_desc *dst, int index)
50
356k
{
51
356k
    if (index >= MP_ARRAY_SIZE(clipboard_backend_list))
52
178k
        return false;
53
178k
    const struct clipboard_backend *backend = clipboard_backend_list[index];
54
178k
    *dst = (struct m_obj_desc) {
55
178k
        .name = backend->name,
56
178k
        .description = backend->desc,
57
178k
    };
58
178k
    return true;
59
356k
}
60
61
static const struct m_obj_list backend_obj_list = {
62
    .get_desc = get_desc,
63
    .description = "clipboard backends",
64
    .allow_trailer = true,
65
    .disallow_positional_parameters = true,
66
    .use_global_options = true,
67
};
68
69
#define OPT_BASE_STRUCT struct clipboard_opts
70
const struct m_sub_options clipboard_conf = {
71
    .opts = (const struct m_option[]) {
72
        {"monitor", OPT_BOOL(monitor), .flags = UPDATE_CLIPBOARD},
73
        {"backends", OPT_SETTINGSLIST(backends, &backend_obj_list),
74
         .flags = UPDATE_CLIPBOARD},
75
        {0}
76
    },
77
    .defaults = &(const struct clipboard_opts) {
78
        .backends = (struct m_obj_settings[]) {
79
            {.name = "win32", .enabled = true},
80
            {.name = "mac", .enabled = true},
81
            {.name = "wayland", .enabled = true},
82
            {.name = "vo", .enabled = true},
83
            {0}
84
        }
85
    },
86
    .size = sizeof(struct clipboard_opts)
87
};
88
89
struct clipboard_ctx *mp_clipboard_create(struct clipboard_init_params *params,
90
                                          struct mpv_global *global)
91
160k
{
92
160k
    struct clipboard_ctx *cl = talloc_ptrtype(NULL, cl);
93
160k
    *cl = (struct clipboard_ctx) {
94
160k
        .log = mp_log_new(cl, global->log, "clipboard"),
95
160k
        .monitor = params->flags & CLIPBOARD_INIT_ENABLE_MONITORING,
96
160k
    };
97
98
642k
    for (int n = 0; params->backends && params->backends[n].name; n++) {
99
642k
        if (!params->backends[n].enabled)
100
0
            continue;
101
1.12M
        for (int i = 0; i < MP_ARRAY_SIZE(clipboard_backend_list); i++) {
102
642k
            const struct clipboard_backend *backend = clipboard_backend_list[i];
103
642k
            if (strcmp(params->backends[n].name, backend->name))
104
481k
                continue;
105
160k
            if (backend->init(cl, params) != CLIPBOARD_SUCCESS)
106
0
                break;
107
160k
            cl->backend = backend;
108
160k
            goto success;
109
160k
        }
110
642k
    }
111
112
0
    MP_WARN(cl, "Failed to initialize any clipboard backend.\n");
113
0
    talloc_free(cl);
114
0
    return NULL;
115
160k
success:
116
160k
    MP_VERBOSE(cl, "Initialized %s clipboard backend.\n", cl->backend->name);
117
160k
    return cl;
118
160k
}
119
120
void mp_clipboard_destroy(struct clipboard_ctx *cl)
121
338k
{
122
338k
    if (cl && cl->backend->uninit)
123
0
        cl->backend->uninit(cl);
124
338k
    talloc_free(cl);
125
338k
}
126
127
bool mp_clipboard_data_changed(struct clipboard_ctx *cl)
128
8.91M
{
129
8.91M
    if (cl && cl->backend->data_changed && cl->monitor)
130
0
        return cl->backend->data_changed(cl);
131
8.91M
    return false;
132
8.91M
}
133
134
int mp_clipboard_get_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
135
                          struct clipboard_data *out, void *talloc_ctx)
136
161
{
137
161
    if (cl && cl->backend->get_data)
138
0
        return cl->backend->get_data(cl, params, out, talloc_ctx);
139
161
    return CLIPBOARD_UNAVAILABLE;
140
161
}
141
142
int mp_clipboard_set_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
143
                          struct clipboard_data *data)
144
0
{
145
0
    if (cl && cl->backend->set_data)
146
0
        return cl->backend->set_data(cl, params, data);
147
0
    return CLIPBOARD_UNAVAILABLE;
148
0
}
149
150
const char *mp_clipboard_get_backend_name(struct clipboard_ctx *cl)
151
24
{
152
24
    return cl ? cl->backend->name : NULL;
153
24
}
154
155
void reinit_clipboard(struct MPContext *mpctx)
156
160k
{
157
160k
    mp_clipboard_destroy(mpctx->clipboard);
158
160k
    mpctx->clipboard = NULL;
159
160
160k
    struct clipboard_opts *opts = mp_get_config_group(NULL, mpctx->global, &clipboard_conf);
161
160k
    if (opts->backends && opts->backends[0].name) {
162
160k
        struct clipboard_init_params params = {
163
160k
            .mpctx = mpctx,
164
160k
            .flags = opts->monitor ? CLIPBOARD_INIT_ENABLE_MONITORING : 0,
165
160k
            .backends = opts->backends,
166
160k
        };
167
160k
        mpctx->clipboard = mp_clipboard_create(&params, mpctx->global);
168
160k
    }
169
160k
    talloc_free(opts);
170
160k
}