|
|
@ -365,7 +365,7 @@ static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) {
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WLC_EVENT_ERROR) {
|
|
|
|
if (mask & WLC_EVENT_ERROR) {
|
|
|
|
sway_log(L_ERROR, "Selection data fd error");
|
|
|
|
sway_log(L_ERROR, "Selection data fd error");
|
|
|
|
goto release;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WLC_EVENT_READABLE) {
|
|
|
|
if (mask & WLC_EVENT_READABLE) {
|
|
|
@ -388,12 +388,12 @@ static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) {
|
|
|
|
if (req->buf_position >= req->buf_size - 1) {
|
|
|
|
if (req->buf_position >= req->buf_size - 1) {
|
|
|
|
if (req->buf_size >= max_size) {
|
|
|
|
if (req->buf_size >= max_size) {
|
|
|
|
sway_log(L_ERROR, "get_clipbard: selection data too large");
|
|
|
|
sway_log(L_ERROR, "get_clipbard: selection data too large");
|
|
|
|
goto release;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char *next = realloc(req->buf, req->buf_size *= 2);
|
|
|
|
char *next = realloc(req->buf, req->buf_size *= 2);
|
|
|
|
if (!next) {
|
|
|
|
if (!next) {
|
|
|
|
sway_log_errno(L_ERROR, "get_clipboard: realloc data buffer failed");
|
|
|
|
sway_log_errno(L_ERROR, "get_clipboard: realloc data buffer failed");
|
|
|
|
goto release;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
req->buf = next;
|
|
|
|
req->buf = next;
|
|
|
@ -402,21 +402,33 @@ static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) {
|
|
|
|
|
|
|
|
|
|
|
|
req->buf[req->buf_position] = '\0';
|
|
|
|
req->buf[req->buf_position] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
|
|
|
|
json_object_object_add(obj, "success", json_object_new_boolean(true));
|
|
|
|
if (is_text_target(req->type)) {
|
|
|
|
if (is_text_target(req->type)) {
|
|
|
|
json_object_object_add(req->json, req->type,
|
|
|
|
json_object_object_add(obj, "content", json_object_new_string(req->buf));
|
|
|
|
json_object_new_string(req->buf));
|
|
|
|
json_object_object_add(req->json, req->type, obj);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
size_t outlen;
|
|
|
|
size_t outlen;
|
|
|
|
char *b64 = b64_encode(req->buf, req->buf_position, &outlen);
|
|
|
|
char *b64 = b64_encode(req->buf, req->buf_position, &outlen);
|
|
|
|
|
|
|
|
json_object_object_add(obj, "content", json_object_new_string(b64));
|
|
|
|
|
|
|
|
free(b64);
|
|
|
|
|
|
|
|
|
|
|
|
char *type = malloc(strlen(req->type) + 8);
|
|
|
|
char *type = malloc(strlen(req->type) + 8);
|
|
|
|
strcat(type, ";base64");
|
|
|
|
strcat(type, ";base64");
|
|
|
|
json_object_object_add(req->json, type,
|
|
|
|
json_object_object_add(req->json, type, obj);
|
|
|
|
json_object_new_string(b64));
|
|
|
|
|
|
|
|
free(type);
|
|
|
|
free(type);
|
|
|
|
free(b64);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
goto release;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error:;
|
|
|
|
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
|
|
|
|
json_object_object_add(obj, "success", json_object_new_boolean(false));
|
|
|
|
|
|
|
|
json_object_object_add(obj, "error",
|
|
|
|
|
|
|
|
json_object_new_string("Failed to retrieve data"));
|
|
|
|
|
|
|
|
json_object_object_add(req->json, req->type, obj);
|
|
|
|
|
|
|
|
|
|
|
|
release:
|
|
|
|
release:
|
|
|
|
release_clipboard_request(req);
|
|
|
|
release_clipboard_request(req);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -427,13 +439,18 @@ static int ipc_selection_timer_cb(void *data) {
|
|
|
|
struct get_clipboard_request *req = (struct get_clipboard_request *)data;
|
|
|
|
struct get_clipboard_request *req = (struct get_clipboard_request *)data;
|
|
|
|
|
|
|
|
|
|
|
|
sway_log(L_INFO, "get_clipbard: timeout for type %s", req->type);
|
|
|
|
sway_log(L_INFO, "get_clipbard: timeout for type %s", req->type);
|
|
|
|
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
|
|
|
|
json_object_object_add(obj, "success", json_object_new_boolean(false));
|
|
|
|
|
|
|
|
json_object_object_add(obj, "error", json_object_new_string("Timeout"));
|
|
|
|
|
|
|
|
json_object_object_add(req->json, req->type, obj);
|
|
|
|
|
|
|
|
|
|
|
|
release_clipboard_request(req);
|
|
|
|
release_clipboard_request(req);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// greedy wildcard (only "*") matching
|
|
|
|
// greedy wildcard (only "*") matching
|
|
|
|
bool mime_type_matches(const char *mime_type, const char *pattern) {
|
|
|
|
bool mime_type_matches(const char *mime_type, const char *pattern) {
|
|
|
|
const char* wildcard = NULL;
|
|
|
|
const char *wildcard = NULL;
|
|
|
|
while (*mime_type && *pattern) {
|
|
|
|
while (*mime_type && *pattern) {
|
|
|
|
if (*pattern == '*' && !wildcard) {
|
|
|
|
if (*pattern == '*' && !wildcard) {
|
|
|
|
wildcard = pattern;
|
|
|
|
wildcard = pattern;
|
|
|
@ -461,9 +478,6 @@ bool mime_type_matches(const char *mime_type, const char *pattern) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ipc_get_clipboard(struct ipc_client *client, char *buf) {
|
|
|
|
void ipc_get_clipboard(struct ipc_client *client, char *buf) {
|
|
|
|
static const char *error_json = "{ \"success\": false, \"error\": "
|
|
|
|
|
|
|
|
"\"Failed to retrieve clipboard data\" }";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t size;
|
|
|
|
size_t size;
|
|
|
|
const char **types = wlc_get_selection_types(&size);
|
|
|
|
const char **types = wlc_get_selection_types(&size);
|
|
|
|
if (client->payload_length == 0) {
|
|
|
|
if (client->payload_length == 0) {
|
|
|
@ -542,7 +556,7 @@ void ipc_get_clipboard(struct ipc_client *client, char *buf) {
|
|
|
|
WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP,
|
|
|
|
WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP,
|
|
|
|
&ipc_selection_data_cb, req);
|
|
|
|
&ipc_selection_data_cb, req);
|
|
|
|
|
|
|
|
|
|
|
|
wlc_event_source_timer_update(req->timer_event_source, 1000);
|
|
|
|
wlc_event_source_timer_update(req->timer_event_source, 30000);
|
|
|
|
|
|
|
|
|
|
|
|
// NOTE: remove this goto to enable retrieving multiple
|
|
|
|
// NOTE: remove this goto to enable retrieving multiple
|
|
|
|
// targets at once. The whole implementation is already
|
|
|
|
// targets at once. The whole implementation is already
|
|
|
@ -561,15 +575,18 @@ void ipc_get_clipboard(struct ipc_client *client, char *buf) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (*pending == 0) {
|
|
|
|
if (*pending == 0) {
|
|
|
|
static const char *empty = "[]";
|
|
|
|
static const char *error_empty = "{ \"success\": false, \"error\": "
|
|
|
|
ipc_send_reply(client, empty, (uint32_t)strlen(empty));
|
|
|
|
"\"No matching types found\" }";
|
|
|
|
|
|
|
|
ipc_send_reply(client, error_empty, (uint32_t)strlen(error_empty));
|
|
|
|
free(json);
|
|
|
|
free(json);
|
|
|
|
free(pending);
|
|
|
|
free(pending);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
|
|
data_error:
|
|
|
|
data_error:;
|
|
|
|
|
|
|
|
static const char *error_json = "{ \"success\": false, \"error\": "
|
|
|
|
|
|
|
|
"\"Failed to create clipboard data request\" }";
|
|
|
|
ipc_send_reply(client, error_json, (uint32_t)strlen(error_json));
|
|
|
|
ipc_send_reply(client, error_json, (uint32_t)strlen(error_json));
|
|
|
|
free(json);
|
|
|
|
free(json);
|
|
|
|
free(pending);
|
|
|
|
free(pending);
|
|
|
|