aboutsummaryrefslogtreecommitdiff
path: root/swt.c
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-04-17 20:33:22 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2023-04-17 20:33:22 +0200
commit7659dfc2894518f124557ba1f2ae493c6c041782 (patch)
treeb45ec5105f6a72ff1a36599dbc0f0957c62809e6 /swt.c
parent4b6ef5f586004c085c6aed3b614161f6e5ab5d3f (diff)
add clipboard support
Diffstat (limited to 'swt.c')
-rw-r--r--swt.c149
1 files changed, 138 insertions, 11 deletions
diff --git a/swt.c b/swt.c
index c444397..6f59256 100644
--- a/swt.c
+++ b/swt.c
@@ -64,7 +64,10 @@ static void setup();
static void cleanup();
static void run();
static void usage();
+static void copy();
+static void paste();
static int matchmod(uint32_t mask, uint32_t mod);
+static int execshortcut();
static char *kmap();
static void buffer_release(void *data, struct wl_buffer *buffer);
static void draw_frame();
@@ -78,6 +81,7 @@ static void registry_global(void *data, struct wl_registry *registry, uint32_t n
static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name);
static void seat_capabilities(void *dat, struct wl_seat *seat, uint32_t capabilities);
static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size);
+static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys);
static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t client);
static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay);
@@ -87,6 +91,10 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t seria
static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y);
static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
+static void data_device_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer);
+static void data_device_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer);
+static void data_source_send(void *data, struct wl_data_source *source, const char *mime_type, int fd);
+static void data_source_cancelled(void *data, struct wl_data_source *source);
static void dummy() {}
@@ -125,11 +133,11 @@ static const struct wl_keyboard_listener keyboard_listener = {
.key = keyboard_key,
.modifiers = keyboard_modifiers,
.repeat_info = keyboard_repeat_info,
- .enter = dummy,
+ .enter = keyboard_enter,
.leave = dummy,
};
-const struct wl_pointer_listener pointer_listener = {
+static const struct wl_pointer_listener pointer_listener = {
.enter = pointer_enter,
.leave = pointer_leave,
.motion = pointer_motion,
@@ -142,6 +150,20 @@ const struct wl_pointer_listener pointer_listener = {
.frame = dummy,
};
+static const struct wl_data_device_listener data_device_listener = {
+ .data_offer = data_device_data_offer,
+ .selection = data_device_selection
+};
+
+static const struct wl_data_source_listener data_source_listener = {
+ .send = data_source_send,
+ .cancelled = data_source_cancelled
+};
+
+static const struct wl_data_offer_listener data_offer_listener = {
+ .offer = dummy,
+};
+
Client client = { 0 };
Window win = { 0 };
@@ -155,15 +177,39 @@ static char **opt_cmd = 0;
#include "config.h"
+static char clipboard[CLIPBOARD_SIZE] = "";
+
/* function implementation */
-void wbell() {
+void
+wbell() {
/* TODO */
}
-void wclipcopy() {
- /* TODO */
+void
+wclipcopy() {
+ copy();
+}
+
+
+void
+copy()
+{
+ struct wl_data_source *source = wl_data_device_manager_create_data_source(client.clipboard.data_device_manager);
+
+ strcpy(clipboard, getsel());
+
+ wl_data_source_add_listener(source, &data_source_listener, 0);
+ wl_data_source_offer(source, "text/plain");
+ wl_data_device_set_selection(client.clipboard.data_device, source, client.clipboard.keyboard_enter_serial);
+}
+
+
+void
+paste()
+{
+ ttywrite(clipboard, strlen(clipboard), 1);
}
@@ -323,7 +369,7 @@ int wgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) {
void wseticontitle(char *title) {
- fprintf(stderr, "SET ICON TITLE: %s\n", title);
+ wsettitle(title);
}
@@ -450,6 +496,7 @@ registry_global(void *data, struct wl_registry *registry, uint32_t name, const c
match_then_bind(client.shm, wl_shm_interface, 1)
or_match match_then_bind(client.compositor, wl_compositor_interface, 4)
or_match match_then_bind(client.wm_base, xdg_wm_base_interface, 1)
+ or_match match_then_bind(client.clipboard.data_device_manager, wl_data_device_manager_interface, 3)
or_match match_then_bind(client.seat, wl_seat_interface, 7)
wl_seat_add_listener(client.seat, &seat_listener, &client);
end_match
@@ -511,6 +558,13 @@ keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32
void
+keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
+{
+ client.clipboard.keyboard_enter_serial = serial;
+}
+
+
+void
keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
struct itimerspec spec = { 0 };
@@ -535,14 +589,13 @@ void
keyboard_modifiers(void *data, struct wl_keyboard *keybaord, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group)
{
xkb_state_update_mask(client.kb.state, depressed, latched, locked, 0, 0, group);
-
client.kb.event.mod = 0;
client.kb.event.mod |= xkb_state_mod_name_is_active(
client.kb.state,
XKB_MOD_NAME_ALT,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED
) * KEY_MOD_ALT;
- client.kb.event.mod = xkb_state_mod_name_is_active(
+ client.kb.event.mod |= xkb_state_mod_name_is_active(
client.kb.state,
XKB_MOD_NAME_CTRL,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED
@@ -571,14 +624,32 @@ keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int
client.kb.repeat.period = -1;
}
-
int
matchmod(uint32_t mask, uint32_t mod)
{
- return mask == KEY_MOD_ANY || mask == mod;
+ return mask == KEY_MOD_ANY || mask & mod;
}
+int
+execshortcut()
+{
+ Shortcut *sc;
+
+ for (sc = shortcut; sc < shortcut + LEN(shortcut); sc++) {
+ if (sc->k != client.kb.event.sym)
+ continue;
+
+ if (!matchmod(sc->mask, client.kb.event.mod))
+ continue;
+
+ sc->func();
+ return 1;
+ }
+
+ return 0;
+}
+
char *
kmap()
{
@@ -607,6 +678,9 @@ handle_keyboard_event()
char c;
if (client.kb.event.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+ if (execshortcut())
+ return;
+
if ((customkey = kmap())) {
ttywrite(customkey, strlen(customkey), 1);
return;
@@ -707,6 +781,56 @@ pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axi
void
+data_device_data_offer(void *data,
+ struct wl_data_device *data_device, struct wl_data_offer *offer) {
+ wl_data_offer_add_listener(offer, &data_offer_listener, NULL);
+}
+
+
+void
+data_device_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
+{
+ int fds[2];
+ ssize_t s;
+
+ if (offer == 0)
+ return;
+
+ pipe(fds);
+ wl_data_offer_receive(offer, "text/plain", fds[1]);
+ close(fds[1]);
+
+ wl_display_roundtrip(client.display);
+
+ s = read(fds[0], clipboard, CLIPBOARD_SIZE - 1);
+ clipboard[s] = 0;
+ close(fds[0]);
+
+ wl_data_offer_destroy(offer);
+}
+
+
+void
+data_source_send(void *data, struct wl_data_source *source, const char *mime_type, int fd)
+{
+ if (strcmp(mime_type, "text/plain") == 0) {
+ write(fd, clipboard, strlen(clipboard));
+ } else {
+ fprintf(stderr, "warning: clipboard request does not support mimetype '%s'", mime_type);
+ }
+
+ close(fd);
+}
+
+
+void
+data_source_cancelled(void *data, struct wl_data_source *source)
+{
+ wl_data_source_destroy(source);
+}
+
+
+void
setup()
{
win.mode = MODE_VISIBLE;
@@ -723,6 +847,10 @@ setup()
xdg_wm_base_add_listener(client.wm_base, &wm_base_listener, &client);
wl_display_roundtrip(client.display);
+ client.clipboard.data_device = wl_data_device_manager_get_data_device(client.clipboard.data_device_manager, client.seat);
+ wl_data_device_add_listener(client.clipboard.data_device, &data_device_listener, 0);
+ wl_display_roundtrip(client.display);
+
client.pointer.pointer = wl_seat_get_pointer(client.seat);
wl_pointer_add_listener(client.pointer.pointer, &pointer_listener, &client);
@@ -827,7 +955,6 @@ usage(void)
int main(int argc, char *argv[])
{
-
ARGBEGIN {
case 'a':
allowaltscreen = 0;