From c47082506714f458e999f6ff1bf3099dfc4c0c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 16:45:26 +0200 Subject: [PATCH 01/20] wip: multi-seat support Compiles and runs, but mouse, clipboard and other things have been disabled. --- input.c | 370 +++++++++++++++++++++++++++------------------------- input.h | 2 +- osc.c | 13 +- render.c | 15 ++- search.c | 23 +++- selection.c | 43 +++++- terminal.c | 49 +++++-- terminal.h | 1 + wayland.c | 268 ++++++++++++++++++++++--------------- wayland.h | 286 ++++++++++++++++++++-------------------- 10 files changed, 617 insertions(+), 453 deletions(-) diff --git a/input.c b/input.c index edfca2f7..75a80b2f 100644 --- a/input.c +++ b/input.c @@ -206,57 +206,58 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, LOG_DBG("keyboard_keymap: keyboard=%p (format=%u, size=%u)", wl_keyboard, format, size); - struct wayland *wayl = data; + struct seat *seat = data; + struct wayland *wayl = seat->wayl; char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (wayl->kbd.xkb_compose_state != NULL) { - xkb_compose_state_unref(wayl->kbd.xkb_compose_state); - wayl->kbd.xkb_compose_state = NULL; + if (seat->kbd.xkb_compose_state != NULL) { + xkb_compose_state_unref(seat->kbd.xkb_compose_state); + seat->kbd.xkb_compose_state = NULL; } - if (wayl->kbd.xkb_compose_table != NULL) { - xkb_compose_table_unref(wayl->kbd.xkb_compose_table); - wayl->kbd.xkb_compose_table = NULL; + if (seat->kbd.xkb_compose_table != NULL) { + xkb_compose_table_unref(seat->kbd.xkb_compose_table); + seat->kbd.xkb_compose_table = NULL; } - if (wayl->kbd.xkb_keymap != NULL) { - xkb_keymap_unref(wayl->kbd.xkb_keymap); - wayl->kbd.xkb_keymap = NULL; + if (seat->kbd.xkb_keymap != NULL) { + xkb_keymap_unref(seat->kbd.xkb_keymap); + seat->kbd.xkb_keymap = NULL; } - if (wayl->kbd.xkb_state != NULL) { - xkb_state_unref(wayl->kbd.xkb_state); - wayl->kbd.xkb_state = NULL; + if (seat->kbd.xkb_state != NULL) { + xkb_state_unref(seat->kbd.xkb_state); + seat->kbd.xkb_state = NULL; } - if (wayl->kbd.xkb != NULL) { - xkb_context_unref(wayl->kbd.xkb); - wayl->kbd.xkb = NULL; + if (seat->kbd.xkb != NULL) { + xkb_context_unref(seat->kbd.xkb); + seat->kbd.xkb = NULL; } - tll_foreach(wayl->kbd.bindings.key, it) + tll_foreach(seat->kbd.bindings.key, it) tll_free(it->item.bind.key_codes); - tll_free(wayl->kbd.bindings.key); + tll_free(seat->kbd.bindings.key); - tll_foreach(wayl->kbd.bindings.search, it) + tll_foreach(seat->kbd.bindings.search, it) tll_free(it->item.bind.key_codes); - tll_free(wayl->kbd.bindings.search); + tll_free(seat->kbd.bindings.search); - wayl->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - wayl->kbd.xkb_keymap = xkb_keymap_new_from_string( - wayl->kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, + seat->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + seat->kbd.xkb_keymap = xkb_keymap_new_from_string( + seat->kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); /* TODO: initialize in enter? */ - wayl->kbd.xkb_state = xkb_state_new(wayl->kbd.xkb_keymap); + seat->kbd.xkb_state = xkb_state_new(seat->kbd.xkb_keymap); - wayl->kbd.mod_shift = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Shift"); - wayl->kbd.mod_alt = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod1") ; - wayl->kbd.mod_ctrl = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Control"); - wayl->kbd.mod_meta = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod4"); + seat->kbd.mod_shift = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Shift"); + seat->kbd.mod_alt = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod1") ; + seat->kbd.mod_ctrl = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Control"); + seat->kbd.mod_meta = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod4"); /* Compose (dead keys) */ - wayl->kbd.xkb_compose_table = xkb_compose_table_new_from_locale( - wayl->kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS); - wayl->kbd.xkb_compose_state = xkb_compose_state_new( - wayl->kbd.xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS); + seat->kbd.xkb_compose_table = xkb_compose_table_new_from_locale( + seat->kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS); + seat->kbd.xkb_compose_state = xkb_compose_state_new( + seat->kbd.xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS); munmap(map_str, size); close(fd); @@ -264,11 +265,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, for (enum bind_action_normal i = 0; i < BIND_ACTION_COUNT; i++) { key_binding_list_t bindings = tll_init(); input_parse_key_binding( - wayl->kbd.xkb_keymap, wayl->conf->bindings.key[i], &bindings); + seat->kbd.xkb_keymap, wayl->conf->bindings.key[i], &bindings); tll_foreach(bindings, it) { tll_push_back( - wayl->kbd.bindings.key, + seat->kbd.bindings.key, ((struct key_binding_normal){.bind = it->item, .action = i})); } @@ -278,11 +279,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, for (enum bind_action_search i = 0; i < BIND_ACTION_SEARCH_COUNT; i++) { key_binding_list_t bindings = tll_init(); input_parse_key_binding( - wayl->kbd.xkb_keymap, wayl->conf->bindings.search[i], &bindings); + seat->kbd.xkb_keymap, wayl->conf->bindings.search[i], &bindings); tll_foreach(bindings, it) { tll_push_back( - wayl->kbd.bindings.search, + seat->kbd.bindings.search, ((struct key_binding_search){.bind = it->item, .action = i})); } @@ -296,28 +297,28 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, { assert(surface != NULL); - struct wayland *wayl = data; + struct seat *seat = data; struct wl_window *win = wl_surface_get_user_data(surface); struct terminal *term = win->term; LOG_DBG("keyboard_enter: keyboard=%p, serial=%u, surface=%p", wl_keyboard, serial, surface); - wayl->kbd_focus = term; - wayl->input_serial = serial; + seat->kbd_focus = term; + seat->input_serial = serial; - term_kbd_focus_in(wayl->kbd_focus); + term_kbd_focus_in(seat->kbd_focus); } static bool -start_repeater(struct wayland *wayl, uint32_t key) +start_repeater(struct seat *seat, uint32_t key) { - if (wayl->kbd.repeat.dont_re_repeat) + if (seat->kbd.repeat.dont_re_repeat) return true; struct itimerspec t = { - .it_value = {.tv_sec = 0, .tv_nsec = wayl->kbd.repeat.delay * 1000000}, - .it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / wayl->kbd.repeat.rate}, + .it_value = {.tv_sec = 0, .tv_nsec = seat->kbd.repeat.delay * 1000000}, + .it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / seat->kbd.repeat.rate}, }; if (t.it_value.tv_nsec >= 1000000000) { @@ -328,23 +329,23 @@ start_repeater(struct wayland *wayl, uint32_t key) t.it_interval.tv_sec += t.it_interval.tv_nsec / 1000000000; t.it_interval.tv_nsec %= 1000000000; } - if (timerfd_settime(wayl->kbd.repeat.fd, 0, &t, NULL) < 0) { - LOG_ERRNO("failed to arm keyboard repeat timer"); + if (timerfd_settime(seat->kbd.repeat.fd, 0, &t, NULL) < 0) { + LOG_ERRNO("%s: failed to arm keyboard repeat timer", seat->name); return false; } - wayl->kbd.repeat.key = key; + seat->kbd.repeat.key = key; return true; } static bool -stop_repeater(struct wayland *wayl, uint32_t key) +stop_repeater(struct seat *seat, uint32_t key) { - if (key != -1 && key != wayl->kbd.repeat.key) + if (key != -1 && key != seat->kbd.repeat.key) return true; - if (timerfd_settime(wayl->kbd.repeat.fd, 0, &(struct itimerspec){}, NULL) < 0) { - LOG_ERRNO("failed to disarm keyboard repeat timer"); + if (timerfd_settime(seat->kbd.repeat.fd, 0, &(struct itimerspec){}, NULL) < 0) { + LOG_ERRNO("%s: failed to disarm keyboard repeat timer", seat->name); return false; } @@ -355,26 +356,26 @@ static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface) { - struct wayland *wayl = data; + struct seat *seat = data; LOG_DBG("keyboard_leave: keyboard=%p, serial=%u, surface=%p", wl_keyboard, serial, surface); assert( - wayl->kbd_focus == NULL || + seat->kbd_focus == NULL || surface == NULL || /* Seen on Sway 1.2 */ - ((const struct wl_window *)wl_surface_get_user_data(surface))->term == wayl->kbd_focus + ((const struct wl_window *)wl_surface_get_user_data(surface))->term == seat->kbd_focus ); - struct terminal *old_focused = wayl->kbd_focus; - wayl->kbd_focus = NULL; + struct terminal *old_focused = seat->kbd_focus; + seat->kbd_focus = NULL; - stop_repeater(wayl, -1); - wayl->kbd.shift = false;; - wayl->kbd.alt = false;; - wayl->kbd.ctrl = false;; - wayl->kbd.meta = false;; - xkb_compose_state_reset(wayl->kbd.xkb_compose_state); + stop_repeater(seat, -1); + seat->kbd.shift = false;; + seat->kbd.alt = false;; + seat->kbd.ctrl = false;; + seat->kbd.meta = false;; + xkb_compose_state_reset(seat->kbd.xkb_compose_state); if (old_focused != NULL) term_kbd_focus_out(old_focused); @@ -508,24 +509,24 @@ static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - struct wayland *wayl = data; - struct terminal *term = wayl->kbd_focus; + struct seat *seat = data; + struct terminal *term = seat->kbd_focus; assert(term != NULL); - const xkb_mod_mask_t ctrl = 1 << wayl->kbd.mod_ctrl; - const xkb_mod_mask_t alt = 1 << wayl->kbd.mod_alt; - const xkb_mod_mask_t shift = 1 << wayl->kbd.mod_shift; - const xkb_mod_mask_t meta = 1 << wayl->kbd.mod_meta; + const xkb_mod_mask_t ctrl = 1 << seat->kbd.mod_ctrl; + const xkb_mod_mask_t alt = 1 << seat->kbd.mod_alt; + const xkb_mod_mask_t shift = 1 << seat->kbd.mod_shift; + const xkb_mod_mask_t meta = 1 << seat->kbd.mod_meta; if (state == XKB_KEY_UP) { - stop_repeater(wayl, key); + stop_repeater(seat, key); return; } key += 8; - bool should_repeat = xkb_keymap_key_repeats(wayl->kbd.xkb_keymap, key); - xkb_keysym_t sym = xkb_state_key_get_one_sym(wayl->kbd.xkb_state, key); + bool should_repeat = xkb_keymap_key_repeats(seat->kbd.xkb_keymap, key); + xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->kbd.xkb_state, key); #if 0 char foo[100]; @@ -533,9 +534,9 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, LOG_INFO("%s", foo); #endif - xkb_compose_state_feed(wayl->kbd.xkb_compose_state, sym); + xkb_compose_state_feed(seat->kbd.xkb_compose_state, sym); enum xkb_compose_status compose_status = xkb_compose_state_get_status( - wayl->kbd.xkb_compose_state); + seat->kbd.xkb_compose_state); if (compose_status == XKB_COMPOSE_COMPOSING) { /* TODO: goto maybe_repeat? */ @@ -543,15 +544,15 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, } xkb_mod_mask_t mods = xkb_state_serialize_mods( - wayl->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); - //xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(wayl->kbd.xkb_state, key); + seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); + //xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(seat->kbd.xkb_state, key); xkb_mod_mask_t consumed = 0x0; xkb_mod_mask_t significant = ctrl | alt | shift | meta; xkb_mod_mask_t effective_mods = mods & ~consumed & significant; if (term->is_searching) { if (should_repeat) - start_repeater(wayl, key - 8); + start_repeater(seat, key - 8); search_input(term, key, sym, effective_mods, serial); return; } @@ -559,7 +560,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, #if 0 for (size_t i = 0; i < 32; i++) { if (mods & (1 << i)) { - LOG_INFO("%s", xkb_keymap_mod_get_name(wayl->kbd.xkb_keymap, i)); + LOG_INFO("%s", xkb_keymap_mod_get_name(seat->kbd.xkb_keymap, i)); } } #endif @@ -573,7 +574,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, /* * User configurable bindings */ - tll_foreach(wayl->kbd.bindings.key, it) { + tll_foreach(seat->kbd.bindings.key, it) { if (it->item.bind.mods != effective_mods) continue; @@ -597,10 +598,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, */ enum modifier keymap_mods = MOD_NONE; - keymap_mods |= wayl->kbd.shift ? MOD_SHIFT : MOD_NONE; - keymap_mods |= wayl->kbd.alt ? MOD_ALT : MOD_NONE; - keymap_mods |= wayl->kbd.ctrl ? MOD_CTRL : MOD_NONE; - keymap_mods |= wayl->kbd.meta ? MOD_META : MOD_NONE; + keymap_mods |= seat->kbd.shift ? MOD_SHIFT : MOD_NONE; + keymap_mods |= seat->kbd.alt ? MOD_ALT : MOD_NONE; + keymap_mods |= seat->kbd.ctrl ? MOD_CTRL : MOD_NONE; + keymap_mods |= seat->kbd.meta ? MOD_META : MOD_NONE; const struct key_data *keymap = keymap_lookup(term, sym, keymap_mods); if (keymap != NULL) { @@ -620,13 +621,13 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (compose_status == XKB_COMPOSE_COMPOSED) { count = xkb_compose_state_get_utf8( - wayl->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); - xkb_compose_state_reset(wayl->kbd.xkb_compose_state); + seat->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); + xkb_compose_state_reset(seat->kbd.xkb_compose_state); } else if (compose_status == XKB_COMPOSE_CANCELLED) { goto maybe_repeat; } else { count = xkb_state_key_get_utf8( - wayl->kbd.xkb_state, key, (char *)buf, sizeof(buf)); + seat->kbd.xkb_state, key, (char *)buf, sizeof(buf)); } if (count == 0) @@ -720,7 +721,7 @@ maybe_repeat: term->wl->presentation_clock_id, &term->render.input_time); if (should_repeat) - start_repeater(wayl, key - 8); + start_repeater(seat, key - 8); } @@ -729,36 +730,36 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - struct wayland *wayl = data; + struct seat *seat = data; LOG_DBG("modifiers: depressed=0x%x, latched=0x%x, locked=0x%x, group=%u", mods_depressed, mods_latched, mods_locked, group); xkb_state_update_mask( - wayl->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); + seat->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); /* Update state of modifiers we're interrested in for e.g mouse events */ - wayl->kbd.shift = xkb_state_mod_index_is_active( - wayl->kbd.xkb_state, wayl->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); - wayl->kbd.alt = xkb_state_mod_index_is_active( - wayl->kbd.xkb_state, wayl->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED); - wayl->kbd.ctrl = xkb_state_mod_index_is_active( - wayl->kbd.xkb_state, wayl->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); - wayl->kbd.meta = xkb_state_mod_index_is_active( - wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); + seat->kbd.shift = xkb_state_mod_index_is_active( + seat->kbd.xkb_state, seat->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); + seat->kbd.alt = xkb_state_mod_index_is_active( + seat->kbd.xkb_state, seat->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED); + seat->kbd.ctrl = xkb_state_mod_index_is_active( + seat->kbd.xkb_state, seat->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); + seat->kbd.meta = xkb_state_mod_index_is_active( + seat->kbd.xkb_state, seat->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); - if (wayl->kbd_focus && wayl->kbd_focus->active_surface == TERM_SURF_GRID) - term_xcursor_update(wayl->kbd_focus); + if (seat->kbd_focus && seat->kbd_focus->active_surface == TERM_SURF_GRID) + term_xcursor_update(seat->kbd_focus); } static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay) { - struct wayland *wayl = data; + struct seat *seat = data; LOG_DBG("keyboard repeat: rate=%d, delay=%d", rate, delay); - wayl->kbd.repeat.rate = rate; - wayl->kbd.repeat.delay = delay; + seat->kbd.repeat.rate = rate; + seat->kbd.repeat.delay = delay; } const struct wl_keyboard_listener keyboard_listener = { @@ -771,9 +772,9 @@ const struct wl_keyboard_listener keyboard_listener = { }; void -input_repeat(struct wayland *wayl, uint32_t key) +input_repeat(struct seat *seat, uint32_t key) { - keyboard_key(wayl, NULL, wayl->input_serial, 0, key, XKB_KEY_DOWN); + keyboard_key(seat, NULL, seat->input_serial, 0, key, XKB_KEY_DOWN); } static bool @@ -838,22 +839,22 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, { assert(surface != NULL); - struct wayland *wayl = data; + struct seat *seat = data; struct wl_window *win = wl_surface_get_user_data(surface); struct terminal *term = win->term; LOG_DBG("pointer-enter: pointer=%p, serial=%u, surface = %p, new-moused = %p", wl_pointer, serial, surface, term); - wayl->mouse_focus = term; + seat->mouse_focus = term; int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; switch ((term->active_surface = term_surface_kind(term, surface))) { case TERM_SURF_GRID: - wayl->mouse.col = x / term->cell_width; - wayl->mouse.row = y / term->cell_height; + seat->mouse.col = x / term->cell_width; + seat->mouse.row = y / term->cell_height; term_xcursor_update(term); break; @@ -889,25 +890,25 @@ static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { - struct wayland *wayl = data; - struct terminal *old_moused = wayl->mouse_focus; + struct seat *seat = data; + struct terminal *old_moused = seat->mouse_focus; LOG_DBG( "pointer-leave: pointer=%p, serial=%u, surface = %p, old-moused = %p", wl_pointer, serial, surface, old_moused); - if (wayl->pointer.xcursor_callback != NULL) { + if (seat->pointer.xcursor_callback != NULL) { /* A cursor frame callback may never be called if the pointer leaves our surface */ - wl_callback_destroy(wayl->pointer.xcursor_callback); - wayl->pointer.xcursor_callback = NULL; - wayl->pointer.pending_terminal = NULL; - wayl->pointer.xcursor = NULL; + wl_callback_destroy(seat->pointer.xcursor_callback); + seat->pointer.xcursor_callback = NULL; + seat->pointer.pending_terminal = NULL; + seat->pointer.xcursor = NULL; } /* Reset mouse state */ - memset(&wayl->mouse, 0, sizeof(wayl->mouse)); + memset(&seat->mouse, 0, sizeof(seat->mouse)); - wayl->mouse_focus = NULL; + seat->mouse_focus = NULL; if (old_moused == NULL) { LOG_WARN( "compositor sent pointer_leave event without a pointer_enter " @@ -953,8 +954,9 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - struct wayland *wayl = data; - struct terminal *term = wayl->mouse_focus; + struct seat *seat = data; + struct wayland *wayl = seat->wayl; + struct terminal *term = seat->mouse_focus; struct wl_window *win = term->window; LOG_DBG("pointer_motion: pointer=%p, x=%d, y=%d", wl_pointer, @@ -965,8 +967,8 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; - wayl->mouse.x = x; - wayl->mouse.y = y; + seat->mouse.x = x; + seat->mouse.y = y; switch (term->active_surface) { case TERM_SURF_NONE: @@ -980,10 +982,10 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, /* We've started a 'move' timer, but user started dragging * right away - abort the timer and initiate the actual move * right away */ - if (wayl->mouse.button == BTN_LEFT && win->csd.move_timeout_fd != -1) { + if (seat->mouse.button == BTN_LEFT && win->csd.move_timeout_fd != -1) { fdm_del(wayl->fdm, win->csd.move_timeout_fd); win->csd.move_timeout_fd = -1; - xdg_toplevel_move(win->xdg_toplevel, wayl->seat, win->csd.serial); + xdg_toplevel_move(win->xdg_toplevel, seat->wl_seat, win->csd.serial); } break; @@ -1002,23 +1004,23 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) return; - bool update_selection = wayl->mouse.button == BTN_LEFT; + bool update_selection = seat->mouse.button == BTN_LEFT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) selection_update(term, col, row); - if (col == wayl->mouse.col && row == wayl->mouse.row) + if (col == seat->mouse.col && row == seat->mouse.row) break; - wayl->mouse.col = col; - wayl->mouse.row = row; + seat->mouse.col = col; + seat->mouse.row = row; if (update_selection && !update_selection_early) selection_update(term, col, row); term_mouse_motion( - term, wayl->mouse.button, wayl->mouse.row, wayl->mouse.col); + term, seat->mouse.button, seat->mouse.row, seat->mouse.col); break; } } @@ -1027,13 +1029,20 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, static bool fdm_csd_move(struct fdm *fdm, int fd, int events, void *data) { - struct wl_window *win = data; - struct wayland *wayl = win->term->wl; - + struct seat *seat = data; fdm_del(fdm, fd); - win->csd.move_timeout_fd = -1; - xdg_toplevel_move(win->xdg_toplevel, wayl->seat, win->csd.serial); + if (seat->mouse_focus == NULL) { + LOG_WARN( + "%s: CSD move timeout triggered, but seat's has no mouse focused terminal", + seat->name); + return true; + } + + struct wl_window *win = seat->mouse_focus->window; + + win->csd.move_timeout_fd = -1; + xdg_toplevel_move(win->xdg_toplevel, seat->wl_seat, win->csd.serial); return true; } @@ -1044,8 +1053,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, LOG_DBG("BUTTON: pointer=%p, serial=%u, button=%x, state=%u", wl_pointer, serial, button, state); - struct wayland *wayl = data; - struct terminal *term = wayl->mouse_focus; + struct seat *seat = data; + struct wayland *wayl = seat->wayl; + struct terminal *term = seat->mouse_focus; assert(term != NULL); @@ -1054,22 +1064,22 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, /* Time since last click */ struct timeval now, since_last; gettimeofday(&now, NULL); - timersub(&now, &wayl->mouse.last_time, &since_last); + timersub(&now, &seat->mouse.last_time, &since_last); /* Double- or triple click? */ - if (button == wayl->mouse.last_button && + if (button == seat->mouse.last_button && since_last.tv_sec == 0 && since_last.tv_usec <= 300 * 1000) { - wayl->mouse.count++; + seat->mouse.count++; } else - wayl->mouse.count = 1; + seat->mouse.count = 1; - wayl->mouse.button = button; /* For motion events */ - wayl->mouse.last_button = button; - wayl->mouse.last_time = now; + seat->mouse.button = button; /* For motion events */ + seat->mouse.last_button = button; + seat->mouse.last_time = now; } else - wayl->mouse.button = 0; /* For motion events */ + seat->mouse.button = 0; /* For motion events */ switch (term->active_surface) { case TERM_SURF_TITLE: @@ -1078,7 +1088,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, struct wl_window *win = term->window; /* Toggle maximized state on double-click */ - if (button == BTN_LEFT && wayl->mouse.count == 2) { + if (button == BTN_LEFT && seat->mouse.count == 2) { if (win->is_maximized) xdg_toplevel_unset_maximized(win->xdg_toplevel); else @@ -1093,7 +1103,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); if (fd >= 0 && timerfd_settime(fd, 0, &timeout, NULL) == 0 && - fdm_add(wayl->fdm, fd, EPOLLIN, &fdm_csd_move, win)) + fdm_add(wayl->fdm, fd, EPOLLIN, &fdm_csd_move, seat)) { win->csd.move_timeout_fd = fd; win->csd.serial = serial; @@ -1127,8 +1137,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) { enum xdg_toplevel_resize_edge resize_type; - int x = wayl->mouse.x; - int y = wayl->mouse.y; + int x = seat->mouse.x; + int y = seat->mouse.y; if (is_top_left(term, x, y)) resize_type = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; @@ -1142,7 +1152,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, resize_type = map[term->active_surface]; xdg_toplevel_resize( - term->window->xdg_toplevel, term->wl->seat, serial, resize_type); + term->window->xdg_toplevel, seat->wl_seat, serial, resize_type); } return; } @@ -1174,32 +1184,32 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, switch (state) { case WL_POINTER_BUTTON_STATE_PRESSED: { - if (button == BTN_LEFT && wayl->mouse.count <= 3) { + if (button == BTN_LEFT && seat->mouse.count <= 3) { selection_cancel(term); if (selection_enabled(term)) { - switch (wayl->mouse.count) { + switch (seat->mouse.count) { case 1: selection_start( - term, wayl->mouse.col, wayl->mouse.row, - wayl->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); break; case 2: - selection_mark_word(term, wayl->mouse.col, wayl->mouse.row, - wayl->kbd.ctrl, serial); + selection_mark_word(term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl, serial); break; case 3: - selection_mark_row(term, wayl->mouse.row, serial); + selection_mark_row(term, seat->mouse.row, serial); break; } } } - else if (button == BTN_RIGHT && wayl->mouse.count == 1) { + else if (button == BTN_RIGHT && seat->mouse.count == 1) { if (selection_enabled(term)) - selection_extend(term, wayl->mouse.col, wayl->mouse.row, serial); + selection_extend(term, seat->mouse.col, seat->mouse.row, serial); } else { @@ -1212,7 +1222,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - if (binding->count != wayl->mouse.count) { + if (binding->count != seat->mouse.count) { /* Not correct click count */ continue; } @@ -1222,7 +1232,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } } - term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col); + term_mouse_down(term, button, seat->mouse.row, seat->mouse.col); break; } @@ -1230,7 +1240,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (button == BTN_LEFT && term->selection.end.col != -1) selection_finalize(term, serial); - term_mouse_up(term, button, wayl->mouse.row, wayl->mouse.col); + term_mouse_up(term, button, seat->mouse.row, seat->mouse.col); break; } break; @@ -1244,9 +1254,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } static void -mouse_scroll(struct wayland *wayl, int amount) +mouse_scroll(struct seat *seat, int amount) { - struct terminal *term = wayl->mouse_focus; + struct terminal *term = seat->mouse_focus; assert(term != NULL); int button = amount < 0 ? BTN_BACK : BTN_FORWARD; @@ -1268,19 +1278,19 @@ mouse_scroll(struct wayland *wayl, int amount) static xkb_keycode_t key_arrow_down = 0; if (key_arrow_up == 0) { - key_arrow_up = xkb_keymap_key_by_name(wayl->kbd.xkb_keymap, "UP"); - key_arrow_down = xkb_keymap_key_by_name(wayl->kbd.xkb_keymap, "DOWN"); + key_arrow_up = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "UP"); + key_arrow_down = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "DOWN"); } xkb_keycode_t key = button == BTN_BACK ? key_arrow_up : key_arrow_down; for (int i = 0; i < amount; i++) - keyboard_key(wayl, NULL, wayl->input_serial, 0, key - 8, XKB_KEY_DOWN); - keyboard_key(wayl, NULL, wayl->input_serial, 0, key - 8, XKB_KEY_UP); + keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_DOWN); + keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_UP); } else { for (int i = 0; i < amount; i++) - term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col); - term_mouse_up(term, button, wayl->mouse.row, wayl->mouse.col); + term_mouse_down(term, button, seat->mouse.row, seat->mouse.col); + term_mouse_up(term, button, seat->mouse.row, seat->mouse.col); scrollback(term, amount); } @@ -1293,9 +1303,9 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; - struct wayland *wayl = data; + struct seat *seat = data; - if (wayl->mouse.have_discrete) + if (seat->mouse.have_discrete) return; /* @@ -1304,11 +1314,11 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, * Without this, very slow scrolling will never actually scroll * anything. */ - wayl->mouse.axis_aggregated += wl_fixed_to_double(value); + seat->mouse.axis_aggregated += wl_fixed_to_double(value); - if (fabs(wayl->mouse.axis_aggregated) >= 1.) { - mouse_scroll(wayl, round(wayl->mouse.axis_aggregated)); - wayl->mouse.axis_aggregated = 0.; + if (fabs(seat->mouse.axis_aggregated) >= 1.) { + mouse_scroll(seat, round(seat->mouse.axis_aggregated)); + seat->mouse.axis_aggregated = 0.; } } @@ -1319,16 +1329,16 @@ wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; - struct wayland *wayl = data; - wayl->mouse.have_discrete = true; - mouse_scroll(wayl, discrete); + struct seat *seat = data; + seat->mouse.have_discrete = true; + mouse_scroll(seat, discrete); } static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { - struct wayland *wayl = data; - wayl->mouse.have_discrete = false; + struct seat *seat = data; + seat->mouse.have_discrete = false; } static void @@ -1344,8 +1354,8 @@ wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; - struct wayland *wayl = data; - wayl->mouse.axis_aggregated = 0.; + struct seat *seat = data; + seat->mouse.axis_aggregated = 0.; } const struct wl_pointer_listener pointer_listener = { diff --git a/input.h b/input.h index 553a6249..c1c14f7c 100644 --- a/input.h +++ b/input.h @@ -8,7 +8,7 @@ extern const struct wl_keyboard_listener keyboard_listener; extern const struct wl_pointer_listener pointer_listener; -void input_repeat(struct wayland *wayl, uint32_t key); +void input_repeat(struct seat *seat, uint32_t key); bool input_parse_key_binding(struct xkb_keymap *keymap, const char *combos, key_binding_list_t *bindings); diff --git a/osc.c b/osc.c index a2702595..1a72cb12 100644 --- a/osc.c +++ b/osc.c @@ -52,6 +52,9 @@ osc_to_clipboard(struct terminal *term, const char *target, } } + (void)to_clipboard; + (void)to_primary; +#if 0 if (to_clipboard) { char *copy = strdup(decoded); if (!text_to_clipboard(term, copy, term->wl->input_serial)) @@ -63,7 +66,7 @@ osc_to_clipboard(struct terminal *term, const char *target, if (!text_to_primary(term, copy, term->wl->input_serial)) free(copy); } - +#endif free(decoded); } @@ -73,6 +76,7 @@ struct clip_context { int idx; }; +#if 0 static void from_clipboard_cb(const char *text, size_t size, void *user) { @@ -117,7 +121,8 @@ from_clipboard_cb(const char *text, size_t size, void *user) term_to_slave(term, chunk, strlen(chunk)); free(chunk); } - +#endif +#if 0 static void from_clipboard_done(void *user) { @@ -133,7 +138,7 @@ from_clipboard_done(void *user) term_to_slave(term, "\033\\", 2); free(ctx); } - +#endif static void osc_from_clipboard(struct terminal *term, const char *source) { @@ -158,6 +163,7 @@ osc_from_clipboard(struct terminal *term, const char *source) struct clip_context *ctx = malloc(sizeof(*ctx)); *ctx = (struct clip_context) {.term = term}; +#if 0 switch (src) { case 'c': text_from_clipboard( @@ -170,6 +176,7 @@ osc_from_clipboard(struct terminal *term, const char *source) text_from_primary(term, &from_clipboard_cb, &from_clipboard_done, ctx); break; } +#endif } static void diff --git a/render.c b/render.c index 391115d6..2a8869ee 100644 --- a/render.c +++ b/render.c @@ -1938,14 +1938,15 @@ render_resize_force(struct terminal *term, int width, int height) { return maybe_resize(term, width, height, true); } - +#if 0 static void xcursor_callback( void *data, struct wl_callback *wl_callback, uint32_t callback_data); - static const struct wl_callback_listener xcursor_listener = { .done = &xcursor_callback, }; +#endif +#if 0 static void render_xcursor_update(struct wayland *wayl, const struct terminal *term) { @@ -1984,7 +1985,9 @@ render_xcursor_update(struct wayland *wayl, const struct terminal *term) wl_surface_commit(wayl->pointer.surface); } +#endif +#if 0 static void xcursor_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) { @@ -1999,12 +2002,13 @@ xcursor_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_ wayl->pointer.pending_terminal = NULL; } } +#endif static void fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) { struct renderer *renderer = data; - struct wayland *wayl = renderer->wayl; + //struct wayland *wayl = renderer->wayl; tll_foreach(renderer->wayl->terms, it) { struct terminal *term = it->item; @@ -2061,6 +2065,7 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) } } +#if 0 if (wayl->pointer.pending_terminal != NULL) { if (wayl->pointer.xcursor_callback == NULL) { render_xcursor_update(wayl, wayl->pointer.pending_terminal); @@ -2069,6 +2074,7 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) /* Frame callback will call render_xcursor_update() */ } } +#endif } void @@ -2100,6 +2106,7 @@ render_refresh_search(struct terminal *term) bool render_xcursor_set(struct terminal *term) { +#if 0 struct wayland *wayl = term->wl; if (wayl->pointer.theme == NULL) @@ -2122,4 +2129,6 @@ render_xcursor_set(struct terminal *term) /* FDM hook takes care of actual rendering */ wayl->pointer.pending_terminal = term; return true; +#endif + return true; } diff --git a/search.c b/search.c index eef7b032..7d52bf47 100644 --- a/search.c +++ b/search.c @@ -18,6 +18,7 @@ #include "shm.h" #include "util.h" +#if 0 static bool search_ensure_size(struct terminal *term, size_t wanted_size) { @@ -36,6 +37,7 @@ search_ensure_size(struct terminal *term, size_t wanted_size) return true; } +#endif static void search_cancel_keep_selection(struct terminal *term) @@ -99,6 +101,7 @@ search_cancel(struct terminal *term) selection_cancel(term); } +#if 0 static void search_update_selection(struct terminal *term, int start_row, int start_col, @@ -168,7 +171,8 @@ search_update_selection(struct terminal *term, selection_update(term, end_col, selection_row); } } - +#endif +#if 0 static void search_find_next(struct terminal *term) { @@ -281,7 +285,8 @@ search_find_next(struct terminal *term) selection_cancel(term); #undef ROW_DEC } - +#endif +#if 0 static void search_match_to_end_of_word(struct terminal *term, bool spaces_only) { @@ -356,7 +361,8 @@ search_match_to_end_of_word(struct terminal *term, bool spaces_only) search_update_selection( term, term->search.match.row, term->search.match.col, end_row, end_col); } - +#endif +#if 0 static size_t distance_next_word(const struct terminal *term) { @@ -384,7 +390,8 @@ distance_next_word(const struct terminal *term) return cursor - term->search.cursor; } - +#endif +#if 0 static size_t distance_prev_word(const struct terminal *term) { @@ -410,7 +417,8 @@ distance_prev_word(const struct terminal *term) return term->search.cursor - cursor; } - +#endif +#if 0 static bool execute_binding(struct terminal *term, enum bind_action_search action, uint32_t serial) @@ -429,8 +437,10 @@ execute_binding(struct terminal *term, enum bind_action_search action, return true; case BIND_ACTION_SEARCH_COMMIT: +#if 0 selection_finalize(term, term->wl->input_serial); search_cancel_keep_selection(term); +#endif return true; case BIND_ACTION_SEARCH_FIND_PREV: @@ -565,11 +575,13 @@ execute_binding(struct terminal *term, enum bind_action_search action, assert(false); return false; } +#endif void search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, uint32_t serial) { +#if 0 LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods); enum xkb_compose_status compose_status = xkb_compose_state_get_status( @@ -641,4 +653,5 @@ update_search: LOG_DBG("search: buffer: %S", term->search.buf); search_find_next(term); render_refresh_search(term); +#endif } diff --git a/selection.c b/selection.c index ae6758f4..dd759e93 100644 --- a/selection.c +++ b/selection.c @@ -624,7 +624,7 @@ selection_extend(struct terminal *term, int col, int row, uint32_t serial) selection_to_primary(term, serial); } -static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener; +//static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener; void selection_finalize(struct terminal *term, uint32_t serial) @@ -741,6 +741,8 @@ selection_mark_row(struct terminal *term, int row, uint32_t serial) selection_finalize(term, serial); } + +#if 0 static void target(void *data, struct wl_data_source *wl_data_source, const char *mime_type) { @@ -865,7 +867,9 @@ static void action(void *data, struct wl_data_source *wl_data_source, uint32_t dnd_action) { } +#endif +#if 0 static const struct wl_data_source_listener data_source_listener = { .target = &target, .send = &send, @@ -874,7 +878,8 @@ static const struct wl_data_source_listener data_source_listener = { .dnd_finished = &dnd_finished, .action = &action, }; - +#endif +#if 0 static void primary_send(void *data, struct zwp_primary_selection_source_v1 *zwp_primary_selection_source_v1, @@ -942,15 +947,18 @@ primary_cancelled(void *data, free(primary->text); primary->text = NULL; } +#endif +#if 0 static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { .send = &primary_send, .cancelled = &primary_cancelled, }; - +#endif bool text_to_clipboard(struct terminal *term, char *text, uint32_t serial) { +#if 0 struct wl_clipboard *clipboard = &term->wl->clipboard; if (clipboard->data_source != NULL) { @@ -983,6 +991,8 @@ text_to_clipboard(struct terminal *term, char *text, uint32_t serial) assert(serial != 0); clipboard->serial = serial; return true; +#endif + return false; } void @@ -1004,6 +1014,7 @@ struct clipboard_receive { void *user; }; +#if 0 static bool fdm_receive(struct fdm *fdm, int fd, int events, void *data) { @@ -1053,7 +1064,8 @@ done: free(ctx); return true; } - +#endif +#if 0 static void begin_receive_clipboard(struct terminal *term, int read_fd, void (*cb)(const char *data, size_t size, void *user), @@ -1081,12 +1093,13 @@ begin_receive_clipboard(struct terminal *term, int read_fd, done(user); } } - +#endif void text_from_clipboard(struct terminal *term, uint32_t serial, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user) { +#if 0 struct wl_clipboard *clipboard = &term->wl->clipboard; if (clipboard->data_offer == NULL) return done(user); @@ -1109,15 +1122,18 @@ text_from_clipboard(struct terminal *term, uint32_t serial, close(write_fd); begin_receive_clipboard(term, read_fd, cb, done, user); +#endif } +#if 0 static void from_clipboard_cb(const char *data, size_t size, void *user) { struct terminal *term = user; term_to_slave(term, data, size); } - +#endif +#if 0 static void from_clipboard_done(void *user) { @@ -1126,10 +1142,11 @@ from_clipboard_done(void *user) if (term->bracketed_paste) term_to_slave(term, "\033[201~", 6); } - +#endif void selection_from_clipboard(struct terminal *term, uint32_t serial) { +#if 0 struct wl_clipboard *clipboard = &term->wl->clipboard; if (clipboard->data_offer == NULL) return; @@ -1139,11 +1156,13 @@ selection_from_clipboard(struct terminal *term, uint32_t serial) text_from_clipboard( term, serial, &from_clipboard_cb, &from_clipboard_done, term); +#endif } bool text_to_primary(struct terminal *term, char *text, uint32_t serial) { +#if 0 if (term->wl->primary_selection_device_manager == NULL) return false; @@ -1183,6 +1202,8 @@ text_to_primary(struct terminal *term, char *text, uint32_t serial) /* Needed when sending the selection to other client */ primary->serial = serial; return true; +#endif + return false; } void @@ -1203,6 +1224,7 @@ text_from_primary( void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user) { +#if 0 if (term->wl->primary_selection_device_manager == NULL) return done(user); @@ -1228,11 +1250,13 @@ text_from_primary( close(write_fd); begin_receive_clipboard(term, read_fd, cb, done, user); +#endif } void selection_from_primary(struct terminal *term) { +#if 0 if (term->wl->primary_selection_device_manager == NULL) return; @@ -1244,6 +1268,7 @@ selection_from_primary(struct terminal *term) term_to_slave(term, "\033[200~", 6); text_from_primary(term, &from_clipboard_cb, &from_clipboard_done, term); +#endif } #if 0 @@ -1303,6 +1328,7 @@ static void selection(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id) { +#if 0 /* Selection offer from other client */ struct wayland *wayl = data; @@ -1316,6 +1342,7 @@ selection(void *data, struct wl_data_device *wl_data_device, if (id != NULL) wl_data_offer_add_listener(id, &data_offer_listener, term); #endif +#endif } const struct wl_data_device_listener data_device_listener = { @@ -1352,6 +1379,7 @@ primary_selection(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device, struct zwp_primary_selection_offer_v1 *id) { +#if 0 /* Selection offer from other client, for primary */ struct wayland *wayl = data; @@ -1367,6 +1395,7 @@ primary_selection(void *data, id, &primary_selection_offer_listener, term); } #endif +#endif } const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { diff --git a/terminal.c b/terminal.c index 0bb545e2..ec46bb76 100644 --- a/terminal.c +++ b/terminal.c @@ -1037,13 +1037,12 @@ fdm_shutdown(struct fdm *fdm, int fd, int events, void *data) * are deferred (for example, when a screen locker is active), and * thus we can get here without having been unmapped. */ - if (wayl->kbd_focus == term) - wayl->kbd_focus = NULL; - if (wayl->mouse_focus == term) - wayl->mouse_focus = NULL; - - assert(wayl->kbd_focus != term); - assert(wayl->mouse_focus != term); + tll_foreach(wayl->seats, it) { + if (it->item.kbd_focus == term) + it->item.kbd_focus = NULL; + if (it->item.mouse_focus == term) + it->item.mouse_focus = NULL; + } void (*cb)(void *, int) = term->shutdown_cb; void *cb_data = term->shutdown_data; @@ -1711,7 +1710,7 @@ void term_cursor_blink_enable(struct terminal *term) { term->cursor_blink.state = CURSOR_BLINK_ON; - term->cursor_blink.active = term->wl->kbd_focus == term + term->cursor_blink.active = term_has_kbd_focus(term) ? cursor_blink_start_timer(term) : true; } @@ -1728,7 +1727,7 @@ term_cursor_blink_restart(struct terminal *term) { if (term->cursor_blink.active) { term->cursor_blink.state = CURSOR_BLINK_ON; - term->cursor_blink.active = term->wl->kbd_focus == term + term->cursor_blink.active = term_has_kbd_focus(term) ? cursor_blink_start_timer(term) : true; } } @@ -1951,6 +1950,17 @@ term_visual_focus_out(struct terminal *term) cursor_refresh(term); } +bool +term_has_kbd_focus(struct terminal *term) +{ + tll_foreach(term->wl->seats, it) { + if (it->item.kbd_focus == term) + return true; + } + + return false; +} + void term_kbd_focus_in(struct terminal *term) { @@ -1965,6 +1975,7 @@ term_kbd_focus_out(struct terminal *term) term_to_slave(term, "\033[O", 3); } +#if 0 static int linux_mouse_button_to_x(int button) { @@ -1983,7 +1994,8 @@ linux_mouse_button_to_x(int button) return -1; } } - +#endif +#if 0 static int encode_xbutton(int xbutton) { @@ -2008,7 +2020,8 @@ encode_xbutton(int xbutton) return -1; } } - +#endif +#if 0 static void report_mouse_click(struct terminal *term, int encoded_button, int row, int col, bool release) @@ -2044,28 +2057,33 @@ report_mouse_click(struct terminal *term, int encoded_button, int row, int col, term_to_slave(term, response, strlen(response)); } - +#endif +#if 0 static void report_mouse_motion(struct terminal *term, int encoded_button, int row, int col) { report_mouse_click(term, encoded_button, row, col, false); } - +#endif bool term_mouse_grabbed(const struct terminal *term) { /* * Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not. */ +#if 0 return term->wl->kbd_focus == term && term->wl->kbd.shift && !term->wl->kbd.alt && /*!term->wl->kbd.ctrl &&*/ !term->wl->kbd.meta; +#endif + return true; } void term_mouse_down(struct terminal *term, int button, int row, int col) { +#if 0 if (term_mouse_grabbed(term)) return; @@ -2101,11 +2119,13 @@ term_mouse_down(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } +#endif } void term_mouse_up(struct terminal *term, int button, int row, int col) { +#if 0 if (term_mouse_grabbed(term)) return; @@ -2145,11 +2165,13 @@ term_mouse_up(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } +#endif } void term_mouse_motion(struct terminal *term, int button, int row, int col) { +#if 0 if (term_mouse_grabbed(term)) return; @@ -2194,6 +2216,7 @@ term_mouse_motion(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } +#endif } void diff --git a/terminal.h b/terminal.h index bcbfbf4d..e28e3af7 100644 --- a/terminal.h +++ b/terminal.h @@ -506,6 +506,7 @@ void term_restore_cursor(struct terminal *term, const struct cursor *cursor); void term_visual_focus_in(struct terminal *term); void term_visual_focus_out(struct terminal *term); +bool term_has_kbd_focus(struct terminal *term); void term_kbd_focus_in(struct terminal *term); void term_kbd_focus_out(struct terminal *term); void term_mouse_down(struct terminal *term, int button, int row, int col); diff --git a/wayland.c b/wayland.c index ae7ead36..da4f658f 100644 --- a/wayland.c +++ b/wayland.c @@ -71,6 +71,59 @@ csd_destroy(struct wl_window *win) } } +static void +seat_destroy(struct seat *seat) +{ + if (seat == NULL) + return; + + tll_foreach(seat->kbd.bindings.key, it) + tll_free(it->item.bind.key_codes); + tll_free(seat->kbd.bindings.key); + + tll_foreach(seat->kbd.bindings.search, it) + tll_free(it->item.bind.key_codes); + tll_free(seat->kbd.bindings.search); + + if (seat->kbd.xkb_compose_state != NULL) + xkb_compose_state_unref(seat->kbd.xkb_compose_state); + if (seat->kbd.xkb_compose_table != NULL) + xkb_compose_table_unref(seat->kbd.xkb_compose_table); + if (seat->kbd.xkb_keymap != NULL) + xkb_keymap_unref(seat->kbd.xkb_keymap); + if (seat->kbd.xkb_state != NULL) + xkb_state_unref(seat->kbd.xkb_state); + if (seat->kbd.xkb != NULL) + xkb_context_unref(seat->kbd.xkb); + + if (seat->kbd.repeat.fd >= 0) + fdm_del(seat->wayl->fdm, seat->kbd.repeat.fd); + + free(seat->pointer.theme_name); + if (seat->pointer.theme != NULL) + wl_cursor_theme_destroy(seat->pointer.theme); + if (seat->pointer.surface != NULL) + wl_surface_destroy(seat->pointer.surface); + if (seat->pointer.xcursor_callback != NULL) + wl_callback_destroy(seat->pointer.xcursor_callback); + + if (seat->primary_selection_device != NULL) + zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); + if (seat->data_device != NULL) + wl_data_device_destroy(seat->data_device); + + if (seat->wl_keyboard != NULL) + wl_keyboard_destroy(seat->wl_keyboard); + if (seat->wl_pointer != NULL) + wl_pointer_destroy(seat->wl_pointer); + if (seat->wl_seat != NULL) + wl_seat_destroy(seat->wl_seat); + + free(seat->clipboard.text); + free(seat->primary.text); + free(seat->name); +} + static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { @@ -98,29 +151,31 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { - struct wayland *wayl = data; + struct seat *seat = data; + assert(seat->wl_seat == wl_seat); + //struct wayland *wayl = data; if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { - if (wayl->keyboard == NULL) { - wayl->keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(wayl->keyboard, &keyboard_listener, wayl); + if (seat->wl_keyboard == NULL) { + seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat); } } else { - if (wayl->keyboard != NULL) { - wl_keyboard_release(wayl->keyboard); - wayl->keyboard = NULL; + if (seat->wl_keyboard != NULL) { + wl_keyboard_release(seat->wl_keyboard); + seat->wl_keyboard = NULL; } } if (caps & WL_SEAT_CAPABILITY_POINTER) { - if (wayl->pointer.pointer == NULL) { - wayl->pointer.pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(wayl->pointer.pointer, &pointer_listener, wayl); + if (seat->wl_pointer == NULL) { + seat->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } } else { - if (wayl->pointer.pointer != NULL) { - wl_pointer_release(wayl->pointer.pointer); - wayl->pointer.pointer = NULL; + if (seat->wl_pointer != NULL) { + wl_pointer_release(seat->wl_pointer); + seat->wl_pointer = NULL; } } } @@ -128,6 +183,9 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, static void seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) { + struct seat *seat = data; + free(seat->name); + seat->name = strdup(name); } static const struct wl_seat_listener seat_listener = { @@ -533,6 +591,32 @@ static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration .configure = &xdg_toplevel_decoration_configure, }; +static bool +fdm_repeat(struct fdm *fdm, int fd, int events, void *data) +{ + if (events & EPOLLHUP) + return false; + + struct seat *seat = data; + uint64_t expiration_count; + ssize_t ret = read( + seat->kbd.repeat.fd, &expiration_count, sizeof(expiration_count)); + + if (ret < 0) { + if (errno == EAGAIN) + return true; + + LOG_ERRNO("failed to read repeat key from repeat timer fd"); + return false; + } + + seat->kbd.repeat.dont_re_repeat = true; + for (size_t i = 0; i < expiration_count; i++) + input_repeat(seat, seat->kbd.repeat.key); + seat->kbd.repeat.dont_re_repeat = false; + return true; +} + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -566,7 +650,6 @@ handle_global(void *data, struct wl_registry *registry, wayl->shm = wl_registry_bind( wayl->registry, name, &wl_shm_interface, required); wl_shm_add_listener(wayl->shm, &shm_listener, wayl); - wl_display_roundtrip(wayl->display); } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { @@ -593,10 +676,55 @@ handle_global(void *data, struct wl_registry *registry, if (!verify_iface_version(interface, version, required)) return; - wayl->seat = wl_registry_bind( + int repeat_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (repeat_fd == -1) { + LOG_ERRNO("failed to create keyboard repeat timer FD"); + return; + } + + struct wl_seat *wl_seat = wl_registry_bind( wayl->registry, name, &wl_seat_interface, required); - wl_seat_add_listener(wayl->seat, &seat_listener, wayl); - wl_display_roundtrip(wayl->display); + + /* Clipboard */ + struct wl_data_device *data_device = wl_data_device_manager_get_data_device( + wayl->data_device_manager, wl_seat); + + /* Primary selection */ + struct zwp_primary_selection_device_v1 *primary_selection_device; + if (wayl->primary_selection_device_manager != NULL) { + primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + wayl->primary_selection_device_manager, wl_seat); + } else + primary_selection_device = NULL; + + tll_push_back(wayl->seats, ((struct seat){ + .wayl = wayl, + .wl_seat = wl_seat, + .wl_name = name, + .kbd = { + .repeat = { + .fd = repeat_fd, + }, + }, + .data_device = data_device, + .primary_selection_device = primary_selection_device, + })); + + struct seat *seat = &tll_back(wayl->seats); + + if (!fdm_add(wayl->fdm, repeat_fd, EPOLLIN, &fdm_repeat, seat)) { + close(repeat_fd); + seat->kbd.repeat.fd = -1; + seat_destroy(seat); + return; + } + + wl_seat_add_listener(wl_seat, &seat_listener, seat); + wl_data_device_add_listener(data_device, &data_device_listener, seat); + if (primary_selection_device != NULL) { + zwp_primary_selection_device_v1_add_listener( + primary_selection_device, &primary_selection_device_listener, seat); + } } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { @@ -629,7 +757,6 @@ handle_global(void *data, struct wl_registry *registry, wayl->xdg_output_manager, mon->output); zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon); } - wl_display_roundtrip(wayl->display); } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { @@ -747,32 +874,6 @@ fdm_wayl(struct fdm *fdm, int fd, int events, void *data) return event_count != -1; } -static bool -fdm_repeat(struct fdm *fdm, int fd, int events, void *data) -{ - if (events & EPOLLHUP) - return false; - - struct wayland *wayl = data; - uint64_t expiration_count; - ssize_t ret = read( - wayl->kbd.repeat.fd, &expiration_count, sizeof(expiration_count)); - - if (ret < 0) { - if (errno == EAGAIN) - return true; - - LOG_ERRNO("failed to read repeat key from repeat timer fd"); - return false; - } - - wayl->kbd.repeat.dont_re_repeat = true; - for (size_t i = 0; i < expiration_count; i++) - input_repeat(wayl, wayl->kbd.repeat.key); - wayl->kbd.repeat.dont_re_repeat = false; - return true; -} - struct wayland * wayl_init(const struct config *conf, struct fdm *fdm) { @@ -780,7 +881,6 @@ wayl_init(const struct config *conf, struct fdm *fdm) wayl->conf = conf; wayl->fdm = fdm; wayl->fd = -1; - wayl->kbd.repeat.fd = -1; if (!fdm_hook_add(fdm, &fdm_hook, wayl, FDM_HOOK_PRIORITY_LOW)) { LOG_ERR("failed to add FDM hook"); @@ -818,20 +918,11 @@ wayl_init(const struct config *conf, struct fdm *fdm) LOG_ERR("no XDG shell interface"); goto out; } - if (wayl->seat == NULL) { - LOG_ERR("no seat available"); - goto out; - } if (wayl->data_device_manager == NULL) { LOG_ERR("no clipboard available " "(wl_data_device_manager not implemented by server)"); goto out; } - if (!wayl->have_argb8888) { - LOG_ERR("compositor does not support ARGB surfaces"); - goto out; - } - if (wayl->primary_selection_device_manager == NULL) LOG_WARN("no primary selection available"); @@ -840,6 +931,13 @@ wayl_init(const struct config *conf, struct fdm *fdm) goto out; } + wl_display_roundtrip(wayl->display); + + if (!wayl->have_argb8888) { + LOG_ERR("compositor does not support ARGB surfaces"); + goto out; + } + tll_foreach(wayl->monitors, it) { LOG_INFO( "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical)", @@ -851,6 +949,7 @@ wayl_init(const struct config *conf, struct fdm *fdm) it->item.ppi.scaled.x, it->item.ppi.scaled.y); } +#if 0 /* Clipboard */ wayl->data_device = wl_data_device_manager_get_data_device( wayl->data_device_manager, wayl->seat); @@ -887,7 +986,7 @@ wayl_init(const struct config *conf, struct fdm *fdm) LOG_ERR("failed to create cursor surface"); goto out; } - +#endif /* All wayland initialization done - make it so */ wl_display_roundtrip(wayl->display); @@ -900,15 +999,6 @@ wayl_init(const struct config *conf, struct fdm *fdm) if (!fdm_add(fdm, wayl->fd, EPOLLIN, &fdm_wayl, wayl)) goto out; - wayl->kbd.repeat.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (wayl->kbd.repeat.fd == -1) { - LOG_ERRNO("failed to create keyboard repeat timer FD"); - goto out; - } - - if (!fdm_add(fdm, wayl->kbd.repeat.fd, EPOLLIN, &fdm_repeat, wayl)) - goto out; - if (wl_display_prepare_read(wayl->display) != 0) { LOG_ERRNO("failed to prepare for reading wayland events"); goto out; @@ -941,16 +1031,13 @@ wayl_destroy(struct wayland *wayl) fdm_hook_del(wayl->fdm, &fdm_hook, FDM_HOOK_PRIORITY_LOW); - if (wayl->kbd.repeat.fd != -1) - fdm_del(wayl->fdm, wayl->kbd.repeat.fd); - - tll_foreach(wayl->monitors, it) { + tll_foreach(wayl->monitors, it) monitor_destroy(&it->item); - tll_remove(wayl->monitors, it); - } + tll_free(wayl->monitors); - if (wayl->pointer.xcursor_callback != NULL) - wl_callback_destroy(wayl->pointer.xcursor_callback); + tll_foreach(wayl->seats, it) + seat_destroy(&it->item); + tll_free(wayl->seats); if (wayl->xdg_output_manager != NULL) zxdg_output_manager_v1_destroy(wayl->xdg_output_manager); @@ -963,25 +1050,7 @@ wayl_destroy(struct wayland *wayl) if (wayl->presentation != NULL) wp_presentation_destroy(wayl->presentation); - tll_foreach(wayl->kbd.bindings.key, it) - tll_free(it->item.bind.key_codes); - tll_free(wayl->kbd.bindings.key); - - tll_foreach(wayl->kbd.bindings.search, it) - tll_free(it->item.bind.key_codes); - tll_free(wayl->kbd.bindings.search); - - if (wayl->kbd.xkb_compose_state != NULL) - xkb_compose_state_unref(wayl->kbd.xkb_compose_state); - if (wayl->kbd.xkb_compose_table != NULL) - xkb_compose_table_unref(wayl->kbd.xkb_compose_table); - if (wayl->kbd.xkb_keymap != NULL) - xkb_keymap_unref(wayl->kbd.xkb_keymap); - if (wayl->kbd.xkb_state != NULL) - xkb_state_unref(wayl->kbd.xkb_state); - if (wayl->kbd.xkb != NULL) - xkb_context_unref(wayl->kbd.xkb); - +#if 0 if (wayl->clipboard.data_source != NULL) wl_data_source_destroy(wayl->clipboard.data_source); if (wayl->clipboard.data_offer != NULL) @@ -993,25 +1062,17 @@ wayl_destroy(struct wayland *wayl) zwp_primary_selection_offer_v1_destroy(wayl->primary.data_offer); free(wayl->primary.text); - free(wayl->pointer.theme_name); - if (wayl->pointer.theme != NULL) - wl_cursor_theme_destroy(wayl->pointer.theme); - if (wayl->pointer.pointer != NULL) - wl_pointer_destroy(wayl->pointer.pointer); - if (wayl->pointer.surface != NULL) - wl_surface_destroy(wayl->pointer.surface); - if (wayl->keyboard != NULL) - wl_keyboard_destroy(wayl->keyboard); if (wayl->data_device != NULL) wl_data_device_destroy(wayl->data_device); +#endif if (wayl->data_device_manager != NULL) wl_data_device_manager_destroy(wayl->data_device_manager); +#if 0 if (wayl->primary_selection_device != NULL) zwp_primary_selection_device_v1_destroy(wayl->primary_selection_device); +#endif if (wayl->primary_selection_device_manager != NULL) zwp_primary_selection_device_manager_v1_destroy(wayl->primary_selection_device_manager); - if (wayl->seat != NULL) - wl_seat_destroy(wayl->seat); if (wayl->shm != NULL) wl_shm_destroy(wayl->shm); if (wayl->sub_compositor != NULL) @@ -1163,6 +1224,7 @@ wayl_win_destroy(struct wl_window *win) static bool wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term) { +#if 0 if (wayl->pointer.size == 0) return true; @@ -1184,6 +1246,8 @@ wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term) } return render_xcursor_set(term); +#endif + return true; } void diff --git a/wayland.h b/wayland.h index ccc03ad3..15dc6057 100644 --- a/wayland.h +++ b/wayland.h @@ -15,65 +15,6 @@ #include "fdm.h" -struct monitor { - struct wayland *wayl; - struct wl_output *output; - struct zxdg_output_v1 *xdg; - uint32_t wl_name; - - int x; - int y; - - struct { - /* Physical size, in mm */ - struct { - int width; - int height; - } mm; - - /* Physical size, in pixels */ - struct { - int width; - int height; - } px_real; - - /* Scaled size, in pixels */ - struct { - int width; - int height; - } px_scaled; - } dim; - - struct { - /* PPI, based on physical size */ - struct { - int x; - int y; - } real; - - /* PPI, logical, based on scaled size */ - struct { - int x; - int y; - } scaled; - } ppi; - - int scale; - float refresh; - enum wl_output_subpixel subpixel; - - /* From wl_output */ - char *make; - char *model; - - /* From xdg_output */ - char *name; - char *description; - - float inch; /* e.g. 24" */ -}; - - typedef tll(xkb_keycode_t) xkb_keycode_list_t; struct key_binding { @@ -138,38 +79,6 @@ struct key_binding_search { enum bind_action_search action; }; -struct kbd { - struct xkb_context *xkb; - struct xkb_keymap *xkb_keymap; - struct xkb_state *xkb_state; - struct xkb_compose_table *xkb_compose_table; - struct xkb_compose_state *xkb_compose_state; - struct { - int fd; - - bool dont_re_repeat; - int32_t delay; - int32_t rate; - uint32_t key; - } repeat; - - xkb_mod_index_t mod_shift; - xkb_mod_index_t mod_alt; - xkb_mod_index_t mod_ctrl; - xkb_mod_index_t mod_meta; - - /* Enabled modifiers */ - bool shift; - bool alt; - bool ctrl; - bool meta; - - struct { - tll(struct key_binding_normal) key; - tll(struct key_binding_search) search; - } bindings; -}; - struct wl_clipboard { struct wl_data_source *data_source; struct wl_data_offer *data_offer; @@ -184,6 +93,91 @@ struct wl_primary { uint32_t serial; }; +struct seat { + struct wayland *wayl; + struct wl_seat *wl_seat; + uint32_t wl_name; + char *name; + + /* Focused terminals */ + struct terminal *kbd_focus; + struct terminal *mouse_focus; + + /* Keyboard state */ + struct wl_keyboard *wl_keyboard; + struct { + struct xkb_context *xkb; + struct xkb_keymap *xkb_keymap; + struct xkb_state *xkb_state; + struct xkb_compose_table *xkb_compose_table; + struct xkb_compose_state *xkb_compose_state; + struct { + int fd; + + bool dont_re_repeat; + int32_t delay; + int32_t rate; + uint32_t key; + } repeat; + + xkb_mod_index_t mod_shift; + xkb_mod_index_t mod_alt; + xkb_mod_index_t mod_ctrl; + xkb_mod_index_t mod_meta; + + /* Enabled modifiers */ + bool shift; + bool alt; + bool ctrl; + bool meta; + + struct { + tll(struct key_binding_normal) key; + tll(struct key_binding_search) search; + } bindings; + } kbd; + + /* Pointer state */ + struct wl_pointer *wl_pointer; + struct { + uint32_t serial; + + struct wl_surface *surface; + struct wl_cursor_theme *theme; + struct wl_cursor *cursor; + int size; + char *theme_name; + const char *xcursor; + + const struct terminal *pending_terminal; + struct wl_callback *xcursor_callback; + } pointer; + + struct { + int x; + int y; + int col; + int row; + int button; + + int count; + int last_button; + struct timeval last_time; + + /* We used a discrete axis event in the current pointer frame */ + double axis_aggregated; + bool have_discrete; + } mouse; + + /* Clipboard */ + uint32_t input_serial; + struct wl_data_device *data_device; + struct zwp_primary_selection_device_v1 *primary_selection_device; + + struct wl_clipboard clipboard; + struct wl_primary primary; +}; + enum csd_surface { CSD_SURF_TITLE, CSD_SURF_LEFT, @@ -196,6 +190,64 @@ enum csd_surface { CSD_SURF_COUNT, }; +struct monitor { + struct wayland *wayl; + struct wl_output *output; + struct zxdg_output_v1 *xdg; + uint32_t wl_name; + + int x; + int y; + + struct { + /* Physical size, in mm */ + struct { + int width; + int height; + } mm; + + /* Physical size, in pixels */ + struct { + int width; + int height; + } px_real; + + /* Scaled size, in pixels */ + struct { + int width; + int height; + } px_scaled; + } dim; + + struct { + /* PPI, based on physical size */ + struct { + int x; + int y; + } real; + + /* PPI, logical, based on scaled size */ + struct { + int x; + int y; + } scaled; + } ppi; + + int scale; + float refresh; + enum wl_output_subpixel subpixel; + + /* From wl_output */ + char *make; + char *model; + + /* From xdg_output */ + char *name; + char *description; + + float inch; /* e.g. 24" */ +}; + struct wayland; struct wl_window { struct terminal *term; @@ -248,67 +300,23 @@ struct wayland { struct wl_subcompositor *sub_compositor; struct wl_shm *shm; - struct wl_seat *seat; - struct wl_keyboard *keyboard; struct zxdg_output_manager_v1 *xdg_output_manager; struct xdg_wm_base *shell; struct zxdg_decoration_manager_v1 *xdg_decoration_manager; + struct wl_data_device_manager *data_device_manager; + struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager; + struct wp_presentation *presentation; uint32_t presentation_clock_id; - /* Keyboard */ - struct kbd kbd; - - /* Clipboard */ - uint32_t input_serial; - struct wl_data_device_manager *data_device_manager; - struct wl_data_device *data_device; - struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager; - struct zwp_primary_selection_device_v1 *primary_selection_device; - - struct wl_clipboard clipboard; - struct wl_primary primary; - - /* Cursor */ - struct { - struct wl_pointer *pointer; - uint32_t serial; - - struct wl_surface *surface; - struct wl_cursor_theme *theme; - struct wl_cursor *cursor; - int size; - char *theme_name; - const char *xcursor; - - const struct terminal *pending_terminal; - struct wl_callback *xcursor_callback; - } pointer; - - struct { - int x; - int y; - int col; - int row; - int button; - - int count; - int last_button; - struct timeval last_time; - - /* We used a discrete axis event in the current pointer frame */ - double axis_aggregated; - bool have_discrete; - } mouse; bool have_argb8888; tll(struct monitor) monitors; /* All available outputs */ + tll(struct seat) seats; tll(struct terminal *) terms; - struct terminal *kbd_focus; - struct terminal *mouse_focus; }; struct wayland *wayl_init(const struct config *conf, struct fdm *fdm); From be2490022d445bef2c5c00336aecf2bd9dd25ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 18:08:39 +0200 Subject: [PATCH 02/20] multi-seat: enable xcursor theme support again --- input.c | 8 ++-- render.c | 90 ++++++++++++++++++--------------------- render.h | 2 +- terminal.c | 21 +++++---- wayland.c | 122 +++++++++++++++++++---------------------------------- wayland.h | 4 +- 6 files changed, 104 insertions(+), 143 deletions(-) diff --git a/input.c b/input.c index 75a80b2f..176d9809 100644 --- a/input.c +++ b/input.c @@ -861,7 +861,7 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_SEARCH: case TERM_SURF_TITLE: term->xcursor = "left_ptr"; - render_xcursor_set(term); + render_xcursor_set(seat, term); break; case TERM_SURF_BORDER_LEFT: @@ -869,14 +869,14 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_BORDER_TOP: case TERM_SURF_BORDER_BOTTOM: term->xcursor = xcursor_for_csd_border(term, x, y); - render_xcursor_set(term); + render_xcursor_set(seat, term); break; case TERM_SURF_BUTTON_MINIMIZE: case TERM_SURF_BUTTON_MAXIMIZE: case TERM_SURF_BUTTON_CLOSE: term->xcursor = "left_ptr"; - render_xcursor_set(term); + render_xcursor_set(seat, term); render_refresh_csd(term); break; @@ -994,7 +994,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_BORDER_TOP: case TERM_SURF_BORDER_BOTTOM: term->xcursor = xcursor_for_csd_border(term, x, y); - render_xcursor_set(term); + render_xcursor_set(seat, term); break; case TERM_SURF_GRID: { diff --git a/render.c b/render.c index 2a8869ee..8fb0fd6f 100644 --- a/render.c +++ b/render.c @@ -1938,77 +1938,72 @@ render_resize_force(struct terminal *term, int width, int height) { return maybe_resize(term, width, height, true); } -#if 0 + static void xcursor_callback( void *data, struct wl_callback *wl_callback, uint32_t callback_data); static const struct wl_callback_listener xcursor_listener = { .done = &xcursor_callback, }; -#endif -#if 0 static void -render_xcursor_update(struct wayland *wayl, const struct terminal *term) +render_xcursor_update(struct seat *seat, const struct terminal *term) { /* If called from a frame callback, we may no longer have mouse focus */ - if (wayl->mouse_focus != term) + if (seat->mouse_focus != term) return; - wayl->pointer.cursor = wl_cursor_theme_get_cursor(wayl->pointer.theme, term->xcursor); - if (wayl->pointer.cursor == NULL) { + seat->pointer.cursor = wl_cursor_theme_get_cursor(seat->pointer.theme, term->xcursor); + if (seat->pointer.cursor == NULL) { LOG_ERR("%s: failed to load xcursor pointer '%s'", - wayl->pointer.theme_name, term->xcursor); + seat->pointer.theme_name, term->xcursor); return; } - wayl->pointer.xcursor = term->xcursor; + seat->pointer.xcursor = term->xcursor; const int scale = term->scale; - struct wl_cursor_image *image = wayl->pointer.cursor->images[0]; + struct wl_cursor_image *image = seat->pointer.cursor->images[0]; wl_surface_attach( - wayl->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); + seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); wl_pointer_set_cursor( - wayl->pointer.pointer, wayl->pointer.serial, - wayl->pointer.surface, + seat->wl_pointer, seat->pointer.serial, + seat->pointer.surface, image->hotspot_x / scale, image->hotspot_y / scale); wl_surface_damage_buffer( - wayl->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); + seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_set_buffer_scale(wayl->pointer.surface, scale); + wl_surface_set_buffer_scale(seat->pointer.surface, scale); - assert(wayl->pointer.xcursor_callback == NULL); - wayl->pointer.xcursor_callback = wl_surface_frame(wayl->pointer.surface); - wl_callback_add_listener(wayl->pointer.xcursor_callback, &xcursor_listener, wayl); + assert(seat->pointer.xcursor_callback == NULL); + seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface); + wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat); - wl_surface_commit(wayl->pointer.surface); + wl_surface_commit(seat->pointer.surface); } -#endif -#if 0 static void xcursor_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) { - struct wayland *wayl = data; + struct seat *seat = data; - assert(wayl->pointer.xcursor_callback == wl_callback); + assert(seat->pointer.xcursor_callback == wl_callback); wl_callback_destroy(wl_callback); - wayl->pointer.xcursor_callback = NULL; + seat->pointer.xcursor_callback = NULL; - if (wayl->pointer.pending_terminal != NULL) { - render_xcursor_update(wayl, wayl->pointer.pending_terminal); - wayl->pointer.pending_terminal = NULL; + if (seat->pointer.pending_terminal != NULL) { + render_xcursor_update(seat, seat->pointer.pending_terminal); + seat->pointer.pending_terminal = NULL; } } -#endif static void fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) { struct renderer *renderer = data; - //struct wayland *wayl = renderer->wayl; + struct wayland *wayl = renderer->wayl; tll_foreach(renderer->wayl->terms, it) { struct terminal *term = it->item; @@ -2065,16 +2060,16 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) } } -#if 0 - if (wayl->pointer.pending_terminal != NULL) { - if (wayl->pointer.xcursor_callback == NULL) { - render_xcursor_update(wayl, wayl->pointer.pending_terminal); - wayl->pointer.pending_terminal = NULL; - } else { - /* Frame callback will call render_xcursor_update() */ + tll_foreach(wayl->seats, it) { + if (it->item.pointer.pending_terminal != NULL) { + if (it->item.pointer.xcursor_callback == NULL) { + render_xcursor_update(&it->item, it->item.pointer.pending_terminal); + it->item.pointer.pending_terminal = NULL; + } else { + /* Frame callback will call render_xcursor_update() */ + } } } -#endif } void @@ -2104,31 +2099,26 @@ render_refresh_search(struct terminal *term) } bool -render_xcursor_set(struct terminal *term) +render_xcursor_set(struct seat *seat, struct terminal *term) { -#if 0 - struct wayland *wayl = term->wl; - - if (wayl->pointer.theme == NULL) + if (seat->pointer.theme == NULL) return false; - if (wayl->mouse_focus == NULL) { - wayl->pointer.xcursor = NULL; - wayl->pointer.pending_terminal = NULL; + if (seat->mouse_focus == NULL) { + seat->pointer.xcursor = NULL; + seat->pointer.pending_terminal = NULL; return true; } - if (wayl->mouse_focus != term) { + if (seat->mouse_focus != term) { /* This terminal doesn't have mouse focus */ return true; } - if (wayl->pointer.xcursor == term->xcursor) + if (seat->pointer.xcursor == term->xcursor) return true; /* FDM hook takes care of actual rendering */ - wayl->pointer.pending_terminal = term; - return true; -#endif + seat->pointer.pending_terminal = term; return true; } diff --git a/render.h b/render.h index 0c03f125..4640145b 100644 --- a/render.h +++ b/render.h @@ -16,7 +16,7 @@ void render_refresh(struct terminal *term); void render_refresh_csd(struct terminal *term); void render_refresh_search(struct terminal *term); void render_refresh_title(struct terminal *term); -bool render_xcursor_set(struct terminal *term); +bool render_xcursor_set(struct seat *seat, struct terminal *term); struct render_worker_context { int my_id; diff --git a/terminal.c b/terminal.c index ec46bb76..add0d199 100644 --- a/terminal.c +++ b/terminal.c @@ -2071,13 +2071,17 @@ term_mouse_grabbed(const struct terminal *term) /* * Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not. */ -#if 0 - return - term->wl->kbd_focus == term && - term->wl->kbd.shift && - !term->wl->kbd.alt && /*!term->wl->kbd.ctrl &&*/ !term->wl->kbd.meta; -#endif - return true; + tll_foreach(term->wl->seats, it) { + const struct seat *seat = &it->item; + + if (seat->kbd_focus == term && + seat->kbd.shift && + !seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.meta) + { + return true; + } + } + return false; } void @@ -2227,7 +2231,8 @@ term_xcursor_update(struct terminal *term) selection_enabled(term) ? XCURSOR_TEXT : XCURSOR_LEFT_PTR; - render_xcursor_set(term); + tll_foreach(term->wl->seats, it) + render_xcursor_set(&it->item, term); } void diff --git a/wayland.c b/wayland.c index da4f658f..19f8ce3e 100644 --- a/wayland.c +++ b/wayland.c @@ -30,8 +30,7 @@ #include "selection.h" #include "util.h" -static bool wayl_reload_cursor_theme( - struct wayland *wayl, struct terminal *term); +static bool wayl_reload_cursor_theme(struct seat *seat, struct terminal *term); static void csd_instantiate(struct wl_window *win) @@ -202,7 +201,9 @@ update_term_for_output_change(struct terminal *term) render_resize(term, term->width / term->scale, term->height / term->scale); term_font_dpi_changed(term); term_font_subpixel_changed(term); - wayl_reload_cursor_theme(term->wl, term); + + tll_foreach(term->wl->seats, it) + wayl_reload_cursor_theme(&it->item, term); } static void @@ -697,6 +698,9 @@ handle_global(void *data, struct wl_registry *registry, } else primary_selection_device = NULL; + struct wl_surface *pointer_surf + = wl_compositor_create_surface(wayl->compositor); + tll_push_back(wayl->seats, ((struct seat){ .wayl = wayl, .wl_seat = wl_seat, @@ -706,6 +710,11 @@ handle_global(void *data, struct wl_registry *registry, .fd = repeat_fd, }, }, + .pointer = { + .surface = pointer_surf, + .size = wayl->xcursor_size, + .theme_name = wayl->xcursor_theme != NULL ? strdup(wayl->xcursor_theme) : NULL, + }, .data_device = data_device, .primary_selection_device = primary_selection_device, })); @@ -882,6 +891,24 @@ wayl_init(const struct config *conf, struct fdm *fdm) wayl->fdm = fdm; wayl->fd = -1; + /* XCursor */ + const char *xcursor_theme = getenv("XCURSOR_THEME"); + if (xcursor_theme != NULL) + wayl->xcursor_theme = strdup(xcursor_theme); + wayl->xcursor_size = 24; + + { + const char *env_cursor_size = getenv("XCURSOR_SIZE"); + if (env_cursor_size != NULL) { + unsigned size; + if (sscanf(env_cursor_size, "%u", &size) == 1) + wayl->xcursor_size = size; + } + } + + LOG_INFO("cursor theme: %s, size: %u", + wayl->xcursor_theme, wayl->xcursor_size); + if (!fdm_hook_add(fdm, &fdm_hook, wayl, FDM_HOOK_PRIORITY_LOW)) { LOG_ERR("failed to add FDM hook"); goto out; @@ -950,45 +977,7 @@ wayl_init(const struct config *conf, struct fdm *fdm) } #if 0 - /* Clipboard */ - wayl->data_device = wl_data_device_manager_get_data_device( - wayl->data_device_manager, wayl->seat); - wl_data_device_add_listener(wayl->data_device, &data_device_listener, wayl); - - /* Primary selection */ - if (wayl->primary_selection_device_manager != NULL) { - wayl->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( - wayl->primary_selection_device_manager, wayl->seat); - zwp_primary_selection_device_v1_add_listener( - wayl->primary_selection_device, &primary_selection_device_listener, wayl); - } - - /* Cursor */ - unsigned cursor_size = 24; - const char *cursor_theme = getenv("XCURSOR_THEME"); - - { - const char *env_cursor_size = getenv("XCURSOR_SIZE"); - if (env_cursor_size != NULL) { - unsigned size; - if (sscanf(env_cursor_size, "%u", &size) == 1) - cursor_size = size; - } - } - - /* Note: theme is (re)loaded on scale and output changes */ - LOG_INFO("cursor theme: %s, size: %u", cursor_theme, cursor_size); - wayl->pointer.size = cursor_size; - wayl->pointer.theme_name = cursor_theme != NULL ? strdup(cursor_theme) : NULL; - - wayl->pointer.surface = wl_compositor_create_surface(wayl->compositor); - if (wayl->pointer.surface == NULL) { - LOG_ERR("failed to create cursor surface"); - goto out; - } #endif - /* All wayland initialization done - make it so */ - wl_display_roundtrip(wayl->display); wayl->fd = wl_display_get_fd(wayl->display); if (fcntl(wayl->fd, F_SETFL, fcntl(wayl->fd, F_GETFL) | O_NONBLOCK) < 0) { @@ -1043,34 +1032,12 @@ wayl_destroy(struct wayland *wayl) zxdg_output_manager_v1_destroy(wayl->xdg_output_manager); if (wayl->shell != NULL) xdg_wm_base_destroy(wayl->shell); - if (wayl->xdg_decoration_manager != NULL) zxdg_decoration_manager_v1_destroy(wayl->xdg_decoration_manager); - if (wayl->presentation != NULL) wp_presentation_destroy(wayl->presentation); - -#if 0 - if (wayl->clipboard.data_source != NULL) - wl_data_source_destroy(wayl->clipboard.data_source); - if (wayl->clipboard.data_offer != NULL) - wl_data_offer_destroy(wayl->clipboard.data_offer); - free(wayl->clipboard.text); - if (wayl->primary.data_source != NULL) - zwp_primary_selection_source_v1_destroy(wayl->primary.data_source); - if (wayl->primary.data_offer != NULL) - zwp_primary_selection_offer_v1_destroy(wayl->primary.data_offer); - free(wayl->primary.text); - - if (wayl->data_device != NULL) - wl_data_device_destroy(wayl->data_device); -#endif if (wayl->data_device_manager != NULL) wl_data_device_manager_destroy(wayl->data_device_manager); -#if 0 - if (wayl->primary_selection_device != NULL) - zwp_primary_selection_device_v1_destroy(wayl->primary_selection_device); -#endif if (wayl->primary_selection_device_manager != NULL) zwp_primary_selection_device_manager_v1_destroy(wayl->primary_selection_device_manager); if (wayl->shm != NULL) @@ -1083,10 +1050,10 @@ wayl_destroy(struct wayland *wayl) wl_registry_destroy(wayl->registry); if (wayl->fd != -1) fdm_del_no_close(wayl->fdm, wayl->fd); - if (wayl->display != NULL) { + if (wayl->display != NULL) wl_display_disconnect(wayl->display); - } + free(wayl->xcursor_theme); free(wayl); } @@ -1222,32 +1189,29 @@ wayl_win_destroy(struct wl_window *win) } static bool -wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term) +wayl_reload_cursor_theme(struct seat *seat, struct terminal *term) { -#if 0 - if (wayl->pointer.size == 0) + if (seat->pointer.size == 0) return true; - if (wayl->pointer.theme != NULL) { - wl_cursor_theme_destroy(wayl->pointer.theme); - wayl->pointer.theme = NULL; - wayl->pointer.cursor = NULL; + if (seat->pointer.theme != NULL) { + wl_cursor_theme_destroy(seat->pointer.theme); + seat->pointer.theme = NULL; + seat->pointer.cursor = NULL; } LOG_DBG("reloading cursor theme: %s@%d", - wayl->pointer.theme_name, wayl->pointer.size); + seat->pointer.theme_name, seat->pointer.size); - wayl->pointer.theme = wl_cursor_theme_load( - wayl->pointer.theme_name, wayl->pointer.size * term->scale, wayl->shm); + seat->pointer.theme = wl_cursor_theme_load( + seat->pointer.theme_name, seat->pointer.size * term->scale, seat->wayl->shm); - if (wayl->pointer.theme == NULL) { + if (seat->pointer.theme == NULL) { LOG_ERR("failed to load cursor theme"); return false; } - return render_xcursor_set(term); -#endif - return true; + return render_xcursor_set(seat, term); } void diff --git a/wayland.h b/wayland.h index 15dc6057..1232563f 100644 --- a/wayland.h +++ b/wayland.h @@ -311,12 +311,14 @@ struct wayland { struct wp_presentation *presentation; uint32_t presentation_clock_id; - bool have_argb8888; tll(struct monitor) monitors; /* All available outputs */ tll(struct seat) seats; tll(struct terminal *) terms; + + char *xcursor_theme; + unsigned xcursor_size; }; struct wayland *wayl_init(const struct config *conf, struct fdm *fdm); From 58415428cf12bd282969e547f65189639ad8351a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 18:16:43 +0200 Subject: [PATCH 03/20] multi-seat: re-enable mouse button+motion reporting support --- input.c | 22 ++++++++++++++++------ terminal.c | 51 ++++++++++++++++++++++----------------------------- terminal.h | 12 +++++++++--- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/input.c b/input.c index 176d9809..67d28102 100644 --- a/input.c +++ b/input.c @@ -1020,7 +1020,8 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, selection_update(term, col, row); term_mouse_motion( - term, seat->mouse.button, seat->mouse.row, seat->mouse.col); + term, seat->mouse.button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); break; } } @@ -1232,7 +1233,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } } - term_mouse_down(term, button, seat->mouse.row, seat->mouse.col); + term_mouse_down( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); break; } @@ -1240,7 +1243,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (button == BTN_LEFT && term->selection.end.col != -1) selection_finalize(term, serial); - term_mouse_up(term, button, seat->mouse.row, seat->mouse.col); + term_mouse_up( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); break; } break; @@ -1288,9 +1293,14 @@ mouse_scroll(struct seat *seat, int amount) keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_DOWN); keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_UP); } else { - for (int i = 0; i < amount; i++) - term_mouse_down(term, button, seat->mouse.row, seat->mouse.col); - term_mouse_up(term, button, seat->mouse.row, seat->mouse.col); + for (int i = 0; i < amount; i++) { + term_mouse_down( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + } + term_mouse_up( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); scrollback(term, amount); } diff --git a/terminal.c b/terminal.c index add0d199..e4197a2a 100644 --- a/terminal.c +++ b/terminal.c @@ -1975,7 +1975,6 @@ term_kbd_focus_out(struct terminal *term) term_to_slave(term, "\033[O", 3); } -#if 0 static int linux_mouse_button_to_x(int button) { @@ -1994,8 +1993,7 @@ linux_mouse_button_to_x(int button) return -1; } } -#endif -#if 0 + static int encode_xbutton(int xbutton) { @@ -2020,8 +2018,7 @@ encode_xbutton(int xbutton) return -1; } } -#endif -#if 0 + static void report_mouse_click(struct terminal *term, int encoded_button, int row, int col, bool release) @@ -2057,14 +2054,13 @@ report_mouse_click(struct terminal *term, int encoded_button, int row, int col, term_to_slave(term, response, strlen(response)); } -#endif -#if 0 + static void report_mouse_motion(struct terminal *term, int encoded_button, int row, int col) { report_mouse_click(term, encoded_button, row, col, false); } -#endif + bool term_mouse_grabbed(const struct terminal *term) { @@ -2085,9 +2081,9 @@ term_mouse_grabbed(const struct terminal *term) } void -term_mouse_down(struct terminal *term, int button, int row, int col) +term_mouse_down(struct terminal *term, int button, int row, int col, + bool _shift, bool _alt, bool _ctrl) { -#if 0 if (term_mouse_grabbed(term)) return; @@ -2101,10 +2097,10 @@ term_mouse_down(struct terminal *term, int button, int row, int col) return; - bool has_focus = term->wl->kbd_focus == term; - bool shift = has_focus ? term->wl->kbd.shift : false; - bool alt = has_focus ? term->wl->kbd.alt : false; - bool ctrl = has_focus ? term->wl->kbd.ctrl : false; + bool has_focus = term_has_kbd_focus(term); + bool shift = has_focus ? _shift : false; + bool alt = has_focus ? _alt : false; + bool ctrl = has_focus ? _ctrl : false; encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); @@ -2123,13 +2119,12 @@ term_mouse_down(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } -#endif } void -term_mouse_up(struct terminal *term, int button, int row, int col) +term_mouse_up(struct terminal *term, int button, int row, int col, + bool _shift, bool _alt, bool _ctrl) { -#if 0 if (term_mouse_grabbed(term)) return; @@ -2147,10 +2142,10 @@ term_mouse_up(struct terminal *term, int button, int row, int col) if (encoded == -1) return; - bool has_focus = term->wl->kbd_focus == term; - bool shift = has_focus ? term->wl->kbd.shift : false; - bool alt = has_focus ? term->wl->kbd.alt : false; - bool ctrl = has_focus ? term->wl->kbd.ctrl : false; + bool has_focus = term_has_kbd_focus(term); + bool shift = has_focus ? _shift : false; + bool alt = has_focus ? _alt : false; + bool ctrl = has_focus ? _ctrl : false; encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); @@ -2169,13 +2164,12 @@ term_mouse_up(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } -#endif } void -term_mouse_motion(struct terminal *term, int button, int row, int col) +term_mouse_motion(struct terminal *term, int button, int row, int col, + bool _shift, bool _alt, bool _ctrl) { -#if 0 if (term_mouse_grabbed(term)) return; @@ -2193,10 +2187,10 @@ term_mouse_motion(struct terminal *term, int button, int row, int col) } else encoded = 3; /* "released" */ - bool has_focus = term->wl->kbd_focus == term; - bool shift = has_focus ? term->wl->kbd.shift : false; - bool alt = has_focus ? term->wl->kbd.alt : false; - bool ctrl = has_focus ? term->wl->kbd.ctrl : false; + bool has_focus = term_has_kbd_focus(term); + bool shift = has_focus ? _shift : false; + bool alt = has_focus ? _alt : false; + bool ctrl = has_focus ? _ctrl : false; encoded += 32; /* Motion event */ encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); @@ -2220,7 +2214,6 @@ term_mouse_motion(struct terminal *term, int button, int row, int col) assert(false && "unimplemented"); break; } -#endif } void diff --git a/terminal.h b/terminal.h index e28e3af7..604511da 100644 --- a/terminal.h +++ b/terminal.h @@ -509,9 +509,15 @@ void term_visual_focus_out(struct terminal *term); bool term_has_kbd_focus(struct terminal *term); void term_kbd_focus_in(struct terminal *term); void term_kbd_focus_out(struct terminal *term); -void term_mouse_down(struct terminal *term, int button, int row, int col); -void term_mouse_up(struct terminal *term, int button, int row, int col); -void term_mouse_motion(struct terminal *term, int button, int row, int col); +void term_mouse_down( + struct terminal *term, int button, int row, int col, + bool shift, bool alt, bool ctrl); +void term_mouse_up( + struct terminal *term, int button, int row, int col, + bool shift, bool alt, bool ctrl); +void term_mouse_motion( + struct terminal *term, int button, int row, int col, + bool shift, bool alt, bool ctrl); bool term_mouse_grabbed(const struct terminal *term); void term_xcursor_update(struct terminal *term); From 04e566492cd831f038afb5ef8908453efca84cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 18:20:34 +0200 Subject: [PATCH 04/20] multi-seat: re-enable scrollback search support --- input.c | 2 +- search.c | 35 ++++++++++++----------------------- search.h | 4 ++-- wayland.c | 4 +--- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/input.c b/input.c index 67d28102..1980e2b5 100644 --- a/input.c +++ b/input.c @@ -553,7 +553,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (term->is_searching) { if (should_repeat) start_repeater(seat, key - 8); - search_input(term, key, sym, effective_mods, serial); + search_input(seat, term, key, sym, effective_mods, serial); return; } diff --git a/search.c b/search.c index 7d52bf47..17b1a05e 100644 --- a/search.c +++ b/search.c @@ -18,7 +18,6 @@ #include "shm.h" #include "util.h" -#if 0 static bool search_ensure_size(struct terminal *term, size_t wanted_size) { @@ -37,7 +36,6 @@ search_ensure_size(struct terminal *term, size_t wanted_size) return true; } -#endif static void search_cancel_keep_selection(struct terminal *term) @@ -101,7 +99,6 @@ search_cancel(struct terminal *term) selection_cancel(term); } -#if 0 static void search_update_selection(struct terminal *term, int start_row, int start_col, @@ -171,8 +168,7 @@ search_update_selection(struct terminal *term, selection_update(term, end_col, selection_row); } } -#endif -#if 0 + static void search_find_next(struct terminal *term) { @@ -285,8 +281,7 @@ search_find_next(struct terminal *term) selection_cancel(term); #undef ROW_DEC } -#endif -#if 0 + static void search_match_to_end_of_word(struct terminal *term, bool spaces_only) { @@ -361,8 +356,7 @@ search_match_to_end_of_word(struct terminal *term, bool spaces_only) search_update_selection( term, term->search.match.row, term->search.match.col, end_row, end_col); } -#endif -#if 0 + static size_t distance_next_word(const struct terminal *term) { @@ -390,8 +384,7 @@ distance_next_word(const struct terminal *term) return cursor - term->search.cursor; } -#endif -#if 0 + static size_t distance_prev_word(const struct terminal *term) { @@ -417,8 +410,7 @@ distance_prev_word(const struct terminal *term) return term->search.cursor - cursor; } -#endif -#if 0 + static bool execute_binding(struct terminal *term, enum bind_action_search action, uint32_t serial) @@ -575,20 +567,18 @@ execute_binding(struct terminal *term, enum bind_action_search action, assert(false); return false; } -#endif void -search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, - xkb_mod_mask_t mods, uint32_t serial) +search_input(struct seat *seat, struct terminal *term, uint32_t key, + xkb_keysym_t sym, xkb_mod_mask_t mods, uint32_t serial) { -#if 0 LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods); enum xkb_compose_status compose_status = xkb_compose_state_get_status( - term->wl->kbd.xkb_compose_state); + seat->kbd.xkb_compose_state); /* Key bindings */ - tll_foreach(term->wl->kbd.bindings.search, it) { + tll_foreach(seat->kbd.bindings.search, it) { if (it->item.bind.mods != mods) continue; @@ -614,13 +604,13 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, if (compose_status == XKB_COMPOSE_COMPOSED) { count = xkb_compose_state_get_utf8( - term->wl->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); - xkb_compose_state_reset(term->wl->kbd.xkb_compose_state); + seat->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); + xkb_compose_state_reset(seat->kbd.xkb_compose_state); } else if (compose_status == XKB_COMPOSE_CANCELLED) { count = 0; } else { count = xkb_state_key_get_utf8( - term->wl->kbd.xkb_state, key, (char *)buf, sizeof(buf)); + seat->kbd.xkb_state, key, (char *)buf, sizeof(buf)); } const char *src = (const char *)buf; @@ -653,5 +643,4 @@ update_search: LOG_DBG("search: buffer: %S", term->search.buf); search_find_next(term); render_refresh_search(term); -#endif } diff --git a/search.h b/search.h index 69930c07..178b6140 100644 --- a/search.h +++ b/search.h @@ -5,5 +5,5 @@ void search_begin(struct terminal *term); void search_cancel(struct terminal *term); -void search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask_t mods, - uint32_t serial); +void search_input(struct seat *seat, struct terminal *term, uint32_t key, + xkb_keysym_t sym, xkb_mod_mask_t mods, uint32_t serial); diff --git a/wayland.c b/wayland.c index 19f8ce3e..54d65927 100644 --- a/wayland.c +++ b/wayland.c @@ -958,6 +958,7 @@ wayl_init(const struct config *conf, struct fdm *fdm) goto out; } + /* Trigger listeners registered when handling globals */ wl_display_roundtrip(wayl->display); if (!wayl->have_argb8888) { @@ -976,9 +977,6 @@ wayl_init(const struct config *conf, struct fdm *fdm) it->item.ppi.scaled.x, it->item.ppi.scaled.y); } -#if 0 -#endif - wayl->fd = wl_display_get_fd(wayl->display); if (fcntl(wayl->fd, F_SETFL, fcntl(wayl->fd, F_GETFL) | O_NONBLOCK) < 0) { LOG_ERRNO("failed to make Wayland socket non-blocking"); From 4c7d29f7eb95b10a0fadc406924db537a18b12ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 18:41:09 +0200 Subject: [PATCH 05/20] multi-seat: re-enable selection support (excluding OSC 52) --- input.c | 31 ++++++------ selection.c | 139 +++++++++++++++++++++------------------------------- selection.h | 35 ++++++++----- wayland.c | 8 +++ 4 files changed, 104 insertions(+), 109 deletions(-) diff --git a/input.c b/input.c index 1980e2b5..a035983a 100644 --- a/input.c +++ b/input.c @@ -33,8 +33,8 @@ #include "vt.h" static void -execute_binding(struct terminal *term, enum bind_action_normal action, - uint32_t serial) +execute_binding(struct seat *seat, struct terminal *term, + enum bind_action_normal action, uint32_t serial) { switch (action) { case BIND_ACTION_NONE: @@ -49,16 +49,16 @@ execute_binding(struct terminal *term, enum bind_action_normal action, break; case BIND_ACTION_CLIPBOARD_COPY: - selection_to_clipboard(term, serial); + selection_to_clipboard(seat, term, serial); break; case BIND_ACTION_CLIPBOARD_PASTE: - selection_from_clipboard(term, serial); + selection_from_clipboard(seat, term, serial); term_reset_view(term); break; case BIND_ACTION_PRIMARY_PASTE: - selection_from_primary(term); + selection_from_primary(seat, term); break; case BIND_ACTION_SEARCH_START: @@ -580,14 +580,14 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, /* Match symbol */ if (it->item.bind.sym == sym) { - execute_binding(term, it->item.action, serial); + execute_binding(seat, term, it->item.action, serial); goto maybe_repeat; } /* Match raw key code */ tll_foreach(it->item.bind.key_codes, code) { if (code->item == key) { - execute_binding(term, it->item.action, serial); + execute_binding(seat, term, it->item.action, serial); goto maybe_repeat; } } @@ -1197,20 +1197,23 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, break; case 2: - selection_mark_word(term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl, serial); + selection_mark_word( + seat, term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl, serial); break; case 3: - selection_mark_row(term, seat->mouse.row, serial); + selection_mark_row(seat, term, seat->mouse.row, serial); break; } } } else if (button == BTN_RIGHT && seat->mouse.count == 1) { - if (selection_enabled(term)) - selection_extend(term, seat->mouse.col, seat->mouse.row, serial); + if (selection_enabled(term)) { + selection_extend( + seat, term, seat->mouse.col, seat->mouse.row, serial); + } } else { @@ -1228,7 +1231,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - execute_binding(term, binding->action, serial); + execute_binding(seat, term, binding->action, serial); break; } } @@ -1241,7 +1244,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, case WL_POINTER_BUTTON_STATE_RELEASED: if (button == BTN_LEFT && term->selection.end.col != -1) - selection_finalize(term, serial); + selection_finalize(seat, term, serial); term_mouse_up( term, button, seat->mouse.row, seat->mouse.col, diff --git a/selection.c b/selection.c index dd759e93..2c8176dd 100644 --- a/selection.c +++ b/selection.c @@ -591,7 +591,8 @@ selection_extend_block(struct terminal *term, int col, int row, uint32_t serial) } void -selection_extend(struct terminal *term, int col, int row, uint32_t serial) +selection_extend(struct seat *seat, struct terminal *term, + int col, int row, uint32_t serial) { if (term->selection.start.row < 0 || term->selection.end.row < 0) { /* No existing selection */ @@ -621,13 +622,13 @@ selection_extend(struct terminal *term, int col, int row, uint32_t serial) break; } - selection_to_primary(term, serial); + selection_to_primary(seat, term, serial); } //static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener; void -selection_finalize(struct terminal *term, uint32_t serial) +selection_finalize(struct seat *seat, struct terminal *term, uint32_t serial) { if (term->selection.start.row < 0 || term->selection.end.row < 0) return; @@ -645,7 +646,7 @@ selection_finalize(struct terminal *term, uint32_t serial) } assert(term->selection.start.row <= term->selection.end.row); - selection_to_primary(term, serial); + selection_to_primary(seat, term, serial); } void @@ -668,8 +669,8 @@ selection_cancel(struct terminal *term) } void -selection_mark_word(struct terminal *term, int col, int row, bool spaces_only, - uint32_t serial) +selection_mark_word(struct seat *seat, struct terminal *term, int col, int row, + bool spaces_only, uint32_t serial) { selection_cancel(term); @@ -730,19 +731,19 @@ selection_mark_word(struct terminal *term, int col, int row, bool spaces_only, selection_start(term, start.col, start.row, SELECTION_NORMAL); selection_update(term, end.col, end.row); - selection_finalize(term, serial); + selection_finalize(seat, term, serial); } void -selection_mark_row(struct terminal *term, int row, uint32_t serial) +selection_mark_row( + struct seat *seat, struct terminal *term, int row, uint32_t serial) { selection_start(term, 0, row, SELECTION_NORMAL); selection_update(term, term->cols - 1, row); - selection_finalize(term, serial); + selection_finalize(seat, term, serial); } -#if 0 static void target(void *data, struct wl_data_source *wl_data_source, const char *mime_type) { @@ -788,8 +789,8 @@ static void send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, int32_t fd) { - struct wayland *wayl = data; - const struct wl_clipboard *clipboard = &wayl->clipboard; + struct seat *seat = data; + const struct wl_clipboard *clipboard = &seat->clipboard; assert(clipboard != NULL); assert(clipboard->text != NULL); @@ -817,7 +818,7 @@ send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, .idx = async_idx, }; - if (fdm_add(wayl->fdm, fd, EPOLLOUT, &fdm_send, ctx)) + if (fdm_add(seat->wayl->fdm, fd, EPOLLOUT, &fdm_send, ctx)) return; free(ctx->data); @@ -841,8 +842,8 @@ send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, static void cancelled(void *data, struct wl_data_source *wl_data_source) { - struct wayland *wayl = data; - struct wl_clipboard *clipboard = &wayl->clipboard; + struct seat *seat = data; + struct wl_clipboard *clipboard = &seat->clipboard; assert(clipboard->data_source == wl_data_source); wl_data_source_destroy(clipboard->data_source); @@ -867,9 +868,7 @@ static void action(void *data, struct wl_data_source *wl_data_source, uint32_t dnd_action) { } -#endif -#if 0 static const struct wl_data_source_listener data_source_listener = { .target = &target, .send = &send, @@ -878,15 +877,14 @@ static const struct wl_data_source_listener data_source_listener = { .dnd_finished = &dnd_finished, .action = &action, }; -#endif -#if 0 + static void primary_send(void *data, struct zwp_primary_selection_source_v1 *zwp_primary_selection_source_v1, const char *mime_type, int32_t fd) { - struct wayland *wayl = data; - const struct wl_primary *primary = &wayl->primary; + struct seat *seat = data; + const struct wl_primary *primary = &seat->primary; assert(primary != NULL); assert(primary->text != NULL); @@ -912,7 +910,7 @@ primary_send(void *data, .idx = async_idx, }; - if (fdm_add(wayl->fdm, fd, EPOLLOUT, &fdm_send, ctx)) + if (fdm_add(seat->wayl->fdm, fd, EPOLLOUT, &fdm_send, ctx)) return; free(ctx->data); @@ -937,8 +935,8 @@ static void primary_cancelled(void *data, struct zwp_primary_selection_source_v1 *zwp_primary_selection_source_v1) { - struct wayland *wayl = data; - struct wl_primary *primary = &wayl->primary; + struct seat *seat = data; + struct wl_primary *primary = &seat->primary; zwp_primary_selection_source_v1_destroy(primary->data_source); primary->data_source = NULL; @@ -947,24 +945,21 @@ primary_cancelled(void *data, free(primary->text); primary->text = NULL; } -#endif -#if 0 static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { .send = &primary_send, .cancelled = &primary_cancelled, }; -#endif + bool -text_to_clipboard(struct terminal *term, char *text, uint32_t serial) +text_to_clipboard(struct seat *seat, struct terminal *term, char *text, uint32_t serial) { -#if 0 - struct wl_clipboard *clipboard = &term->wl->clipboard; + struct wl_clipboard *clipboard = &seat->clipboard; if (clipboard->data_source != NULL) { /* Kill previous data source */ assert(clipboard->serial != 0); - wl_data_device_set_selection(term->wl->data_device, NULL, clipboard->serial); + wl_data_device_set_selection(seat->data_device, NULL, clipboard->serial); wl_data_source_destroy(clipboard->data_source); free(clipboard->text); @@ -984,26 +979,24 @@ text_to_clipboard(struct terminal *term, char *text, uint32_t serial) /* Configure source */ wl_data_source_offer(clipboard->data_source, "text/plain;charset=utf-8"); - wl_data_source_add_listener(clipboard->data_source, &data_source_listener, term->wl); - wl_data_device_set_selection(term->wl->data_device, clipboard->data_source, serial); + wl_data_source_add_listener(clipboard->data_source, &data_source_listener, seat); + wl_data_device_set_selection(seat->data_device, clipboard->data_source, serial); /* Needed when sending the selection to other client */ assert(serial != 0); clipboard->serial = serial; return true; -#endif - return false; } void -selection_to_clipboard(struct terminal *term, uint32_t serial) +selection_to_clipboard(struct seat *seat, struct terminal *term, uint32_t serial) { if (term->selection.start.row < 0 || term->selection.end.row < 0) return; /* Get selection as a string */ char *text = extract_selection(term); - if (!text_to_clipboard(term, text, serial)) + if (!text_to_clipboard(seat, term, text, serial)) free(text); } @@ -1014,7 +1007,7 @@ struct clipboard_receive { void *user; }; -#if 0 + static bool fdm_receive(struct fdm *fdm, int fd, int events, void *data) { @@ -1064,8 +1057,7 @@ done: free(ctx); return true; } -#endif -#if 0 + static void begin_receive_clipboard(struct terminal *term, int read_fd, void (*cb)(const char *data, size_t size, void *user), @@ -1093,14 +1085,13 @@ begin_receive_clipboard(struct terminal *term, int read_fd, done(user); } } -#endif + void -text_from_clipboard(struct terminal *term, uint32_t serial, +text_from_clipboard(struct seat *seat, struct terminal *term, uint32_t serial, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user) { -#if 0 - struct wl_clipboard *clipboard = &term->wl->clipboard; + struct wl_clipboard *clipboard = &seat->clipboard; if (clipboard->data_offer == NULL) return done(user); @@ -1122,18 +1113,15 @@ text_from_clipboard(struct terminal *term, uint32_t serial, close(write_fd); begin_receive_clipboard(term, read_fd, cb, done, user); -#endif } -#if 0 static void from_clipboard_cb(const char *data, size_t size, void *user) { struct terminal *term = user; term_to_slave(term, data, size); } -#endif -#if 0 + static void from_clipboard_done(void *user) { @@ -1142,12 +1130,11 @@ from_clipboard_done(void *user) if (term->bracketed_paste) term_to_slave(term, "\033[201~", 6); } -#endif + void -selection_from_clipboard(struct terminal *term, uint32_t serial) +selection_from_clipboard(struct seat *seat, struct terminal *term, uint32_t serial) { -#if 0 - struct wl_clipboard *clipboard = &term->wl->clipboard; + struct wl_clipboard *clipboard = &seat->clipboard; if (clipboard->data_offer == NULL) return; @@ -1155,26 +1142,24 @@ selection_from_clipboard(struct terminal *term, uint32_t serial) term_to_slave(term, "\033[200~", 6); text_from_clipboard( - term, serial, &from_clipboard_cb, &from_clipboard_done, term); -#endif + seat, term, serial, &from_clipboard_cb, &from_clipboard_done, term); } bool -text_to_primary(struct terminal *term, char *text, uint32_t serial) +text_to_primary(struct seat *seat, struct terminal *term, char *text, uint32_t serial) { -#if 0 if (term->wl->primary_selection_device_manager == NULL) return false; - struct wl_primary *primary = &term->wl->primary; + struct wl_primary *primary = &seat->primary; /* TODO: somehow share code with the clipboard equivalent */ - if (term->wl->primary.data_source != NULL) { + if (seat->primary.data_source != NULL) { /* Kill previous data source */ assert(primary->serial != 0); zwp_primary_selection_device_v1_set_selection( - term->wl->primary_selection_device, NULL, primary->serial); + seat->primary_selection_device, NULL, primary->serial); zwp_primary_selection_source_v1_destroy(primary->data_source); free(primary->text); @@ -1196,39 +1181,36 @@ text_to_primary(struct terminal *term, char *text, uint32_t serial) /* Configure source */ zwp_primary_selection_source_v1_offer(primary->data_source, "text/plain;charset=utf-8"); - zwp_primary_selection_source_v1_add_listener(primary->data_source, &primary_selection_source_listener, term->wl); - zwp_primary_selection_device_v1_set_selection(term->wl->primary_selection_device, primary->data_source, serial); + zwp_primary_selection_source_v1_add_listener(primary->data_source, &primary_selection_source_listener, seat); + zwp_primary_selection_device_v1_set_selection(seat->primary_selection_device, primary->data_source, serial); /* Needed when sending the selection to other client */ primary->serial = serial; return true; -#endif - return false; } void -selection_to_primary(struct terminal *term, uint32_t serial) +selection_to_primary(struct seat *seat, struct terminal *term, uint32_t serial) { if (term->wl->primary_selection_device_manager == NULL) return; /* Get selection as a string */ char *text = extract_selection(term); - if (!text_to_primary(term, text, serial)) + if (!text_to_primary(seat, term, text, serial)) free(text); } void text_from_primary( - struct terminal *term, + struct seat *seat, struct terminal *term, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user) { -#if 0 if (term->wl->primary_selection_device_manager == NULL) return done(user); - struct wl_primary *primary = &term->wl->primary; + struct wl_primary *primary = &seat->primary; if (primary->data_offer == NULL) return done(user); @@ -1250,25 +1232,22 @@ text_from_primary( close(write_fd); begin_receive_clipboard(term, read_fd, cb, done, user); -#endif } void -selection_from_primary(struct terminal *term) +selection_from_primary(struct seat *seat, struct terminal *term) { -#if 0 if (term->wl->primary_selection_device_manager == NULL) return; - struct wl_clipboard *clipboard = &term->wl->clipboard; + struct wl_clipboard *clipboard = &seat->clipboard; if (clipboard->data_offer == NULL) return; if (term->bracketed_paste) term_to_slave(term, "\033[200~", 6); - text_from_primary(term, &from_clipboard_cb, &from_clipboard_done, term); -#endif + text_from_primary(seat, term, &from_clipboard_cb, &from_clipboard_done, term); } #if 0 @@ -1328,11 +1307,10 @@ static void selection(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id) { -#if 0 /* Selection offer from other client */ - struct wayland *wayl = data; - struct wl_clipboard *clipboard = &wayl->clipboard; + struct seat *seat = data; + struct wl_clipboard *clipboard = &seat->clipboard; if (clipboard->data_offer != NULL) wl_data_offer_destroy(clipboard->data_offer); @@ -1342,7 +1320,6 @@ selection(void *data, struct wl_data_device *wl_data_device, if (id != NULL) wl_data_offer_add_listener(id, &data_offer_listener, term); #endif -#endif } const struct wl_data_device_listener data_device_listener = { @@ -1379,11 +1356,10 @@ primary_selection(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device, struct zwp_primary_selection_offer_v1 *id) { -#if 0 /* Selection offer from other client, for primary */ - struct wayland *wayl = data; - struct wl_primary *primary = &wayl->primary; + struct seat *seat = data; + struct wl_primary *primary = &seat->primary; if (primary->data_offer != NULL) zwp_primary_selection_offer_v1_destroy(primary->data_offer); @@ -1395,7 +1371,6 @@ primary_selection(void *data, id, &primary_selection_offer_listener, term); } #endif -#endif } const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { diff --git a/selection.h b/selection.h index 758d5d29..e049f182 100644 --- a/selection.h +++ b/selection.h @@ -12,28 +12,37 @@ bool selection_enabled(const struct terminal *term); void selection_start( struct terminal *term, int col, int row, enum selection_kind kind); void selection_update(struct terminal *term, int col, int row); -void selection_finalize(struct terminal *term, uint32_t serial); +void selection_finalize( + struct seat *seat, struct terminal *term, uint32_t serial); void selection_dirty_cells(struct terminal *term); void selection_cancel(struct terminal *term); -void selection_extend(struct terminal *term, int col, int row, uint32_t serial); +void selection_extend( struct seat *seat, struct terminal *term, + int col, int row, uint32_t serial); bool selection_on_rows(const struct terminal *term, int start, int end); void selection_view_up(struct terminal *term, int new_view); void selection_view_down(struct terminal *term, int new_view); -void selection_mark_word(struct terminal *term, int col, int row, - bool spaces_only, uint32_t serial); -void selection_mark_row(struct terminal *term, int row, uint32_t serial); +void selection_mark_word( + struct seat *seat, struct terminal *term, int col, int row, + bool spaces_only, uint32_t serial); +void selection_mark_row( + struct seat *seat, struct terminal *term, int row, uint32_t serial); -void selection_to_clipboard(struct terminal *term, uint32_t serial); -void selection_from_clipboard(struct terminal *term, uint32_t serial); -void selection_to_primary(struct terminal *term, uint32_t serial); -void selection_from_primary(struct terminal *term); +void selection_to_clipboard( + struct seat *seat, struct terminal *term, uint32_t serial); +void selection_from_clipboard( + struct seat *seat, struct terminal *term, uint32_t serial); +void selection_to_primary( + struct seat *seat, struct terminal *term, uint32_t serial); +void selection_from_primary(struct seat *seat, struct terminal *term); /* Copy text *to* primary/clipboard */ -bool text_to_clipboard(struct terminal *term, char *text, uint32_t serial); -bool text_to_primary(struct terminal *term, char *text, uint32_t serial); +bool text_to_clipboard( + struct seat *seat, struct terminal *term, char *text, uint32_t serial); +bool text_to_primary( + struct seat *seat, struct terminal *term, char *text, uint32_t serial); /* * Copy text *from* primary/clipboard @@ -50,11 +59,11 @@ bool text_to_primary(struct terminal *term, char *text, uint32_t serial); * point). */ void text_from_clipboard( - struct terminal *term, uint32_t serial, + struct seat *seat, struct terminal *term, uint32_t serial, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user); void text_from_primary( - struct terminal *term, + struct seat *seat, struct terminal *term, void (*cb)(const char *data, size_t size, void *user), void (*dont)(void *user), void *user); diff --git a/wayland.c b/wayland.c index 54d65927..f9ec4483 100644 --- a/wayland.c +++ b/wayland.c @@ -106,6 +106,14 @@ seat_destroy(struct seat *seat) if (seat->pointer.xcursor_callback != NULL) wl_callback_destroy(seat->pointer.xcursor_callback); + if (seat->clipboard.data_source != NULL) + wl_data_source_destroy(seat->clipboard.data_source); + if (seat->clipboard.data_offer != NULL) + wl_data_offer_destroy(seat->clipboard.data_offer); + if (seat->primary.data_source != NULL) + zwp_primary_selection_source_v1_destroy(seat->primary.data_source); + if (seat->primary.data_offer != NULL) + zwp_primary_selection_offer_v1_destroy(seat->primary.data_offer); if (seat->primary_selection_device != NULL) zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); if (seat->data_device != NULL) From 11373a65616e4062dc625021b4259e8d227ed5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 19:28:08 +0200 Subject: [PATCH 06/20] multi-seat: re-enable OSC 52 support --- osc.c | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/osc.c b/osc.c index 1a72cb12..3183f196 100644 --- a/osc.c +++ b/osc.c @@ -52,31 +52,42 @@ osc_to_clipboard(struct terminal *term, const char *target, } } - (void)to_clipboard; - (void)to_primary; -#if 0 + /* Find a seat in which the terminal has focus */ + struct seat *seat = NULL; + tll_foreach(term->wl->seats, it) { + if (it->item.kbd_focus == term) { + seat = &it->item; + break; + } + } + + if (seat == NULL) { + LOG_WARN("OSC52: client tried to write to clipboard data while window was unfocused"); + return; + } + if (to_clipboard) { char *copy = strdup(decoded); - if (!text_to_clipboard(term, copy, term->wl->input_serial)) + if (!text_to_clipboard(seat, term, copy, seat->input_serial)) free(copy); } if (to_primary) { char *copy = strdup(decoded); - if (!text_to_primary(term, copy, term->wl->input_serial)) + if (!text_to_primary(seat, term, copy, seat->input_serial)) free(copy); } -#endif + free(decoded); } struct clip_context { + struct seat *seat; struct terminal *term; uint8_t buf[3]; int idx; }; -#if 0 static void from_clipboard_cb(const char *text, size_t size, void *user) { @@ -121,8 +132,7 @@ from_clipboard_cb(const char *text, size_t size, void *user) term_to_slave(term, chunk, strlen(chunk)); free(chunk); } -#endif -#if 0 + static void from_clipboard_done(void *user) { @@ -138,7 +148,7 @@ from_clipboard_done(void *user) term_to_slave(term, "\033\\", 2); free(ctx); } -#endif + static void osc_from_clipboard(struct terminal *term, const char *source) { @@ -156,27 +166,40 @@ osc_from_clipboard(struct terminal *term, const char *source) if (src == 0) return; + /* Find a seat in which the terminal has focus */ + struct seat *seat = NULL; + tll_foreach(term->wl->seats, it) { + if (it->item.kbd_focus == term) { + seat = &it->item; + break; + } + } + + if (seat == NULL) { + LOG_WARN("OSC52: client tried to read clipboard data while window was unfocused"); + return; + } + term_to_slave(term, "\033]52;", 5); term_to_slave(term, &src, 1); term_to_slave(term, ";", 1); struct clip_context *ctx = malloc(sizeof(*ctx)); - *ctx = (struct clip_context) {.term = term}; + *ctx = (struct clip_context) {.seat = seat, .term = term}; -#if 0 switch (src) { case 'c': text_from_clipboard( - term, term->wl->input_serial, + seat, term, seat->input_serial, &from_clipboard_cb, &from_clipboard_done, ctx); break; case 's': case 'p': - text_from_primary(term, &from_clipboard_cb, &from_clipboard_done, ctx); + text_from_primary( + seat, term, &from_clipboard_cb, &from_clipboard_done, ctx); break; } -#endif } static void From 5539af25970e4590faafaba467a3df193534c299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 19:30:34 +0200 Subject: [PATCH 07/20] wayland: seat: log keyboard/pointer capability --- wayland.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index f9ec4483..8b4292ae 100644 --- a/wayland.c +++ b/wayland.c @@ -160,7 +160,10 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, { struct seat *seat = data; assert(seat->wl_seat == wl_seat); - //struct wayland *wayl = data; + + LOG_DBG("%s: keyboard=%s, pointer=%s", seat->name, + (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? "yes" : "no", + (caps & WL_SEAT_CAPABILITY_POINTER) ? "yes" : "no"); if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { if (seat->wl_keyboard == NULL) { From d377221e247f67f7b5e6363f81ae2268e16aa32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 19:52:17 +0200 Subject: [PATCH 08/20] xcursor: trigger theme reload in pointer-enter event Previously, we triggered a theme reload on output changes. This is completely wrong. We may get a new output with a scale different from the output the pointer is actually on. Now, we store the current scale along with the theme. We then trigger a call to reload the xcursor theme *every* time the pointer enters a surface. When it does, we use the current scale factor of the terminal that owns that surface. If the terminal covers multiple outputs, with different scale factors, we'll use the largest scale factor. This may not be 100% correct. But to fix that, we'd need to track which regions of a surface are mapped on which outputs. Too complicated I say. --- input.c | 3 +++ wayland.c | 20 +++++++++++--------- wayland.h | 3 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/input.c b/input.c index a035983a..ea344c99 100644 --- a/input.c +++ b/input.c @@ -846,6 +846,9 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, LOG_DBG("pointer-enter: pointer=%p, serial=%u, surface = %p, new-moused = %p", wl_pointer, serial, surface, term); + /* Scale may have changed */ + wayl_reload_xcursor_theme(seat, term->scale); + seat->mouse_focus = term; int x = wl_fixed_to_int(surface_x) * term->scale; diff --git a/wayland.c b/wayland.c index 8b4292ae..667ae2da 100644 --- a/wayland.c +++ b/wayland.c @@ -30,8 +30,6 @@ #include "selection.h" #include "util.h" -static bool wayl_reload_cursor_theme(struct seat *seat, struct terminal *term); - static void csd_instantiate(struct wl_window *win) { @@ -212,9 +210,6 @@ update_term_for_output_change(struct terminal *term) render_resize(term, term->width / term->scale, term->height / term->scale); term_font_dpi_changed(term); term_font_subpixel_changed(term); - - tll_foreach(term->wl->seats, it) - wayl_reload_cursor_theme(&it->item, term); } static void @@ -1197,13 +1192,19 @@ wayl_win_destroy(struct wl_window *win) free(win); } -static bool -wayl_reload_cursor_theme(struct seat *seat, struct terminal *term) +bool +wayl_reload_xcursor_theme(struct seat *seat, int new_scale) { if (seat->pointer.size == 0) return true; + if (seat->pointer.theme != NULL && seat->pointer.scale == new_scale) { + /* We already have a theme loaded, and the scale hasn't changed */ + return true; + } + if (seat->pointer.theme != NULL) { + assert(seat->pointer.scale != new_scale); wl_cursor_theme_destroy(seat->pointer.theme); seat->pointer.theme = NULL; seat->pointer.cursor = NULL; @@ -1213,14 +1214,15 @@ wayl_reload_cursor_theme(struct seat *seat, struct terminal *term) seat->pointer.theme_name, seat->pointer.size); seat->pointer.theme = wl_cursor_theme_load( - seat->pointer.theme_name, seat->pointer.size * term->scale, seat->wayl->shm); + seat->pointer.theme_name, seat->pointer.size * new_scale, seat->wayl->shm); if (seat->pointer.theme == NULL) { LOG_ERR("failed to load cursor theme"); return false; } - return render_xcursor_set(seat, term); + seat->pointer.scale = new_scale; + return true; } void diff --git a/wayland.h b/wayland.h index 1232563f..489f485d 100644 --- a/wayland.h +++ b/wayland.h @@ -146,6 +146,7 @@ struct seat { struct wl_cursor_theme *theme; struct wl_cursor *cursor; int size; + int scale; char *theme_name; const char *xcursor; @@ -329,3 +330,5 @@ void wayl_roundtrip(struct wayland *wayl); struct wl_window *wayl_win_init(struct terminal *term); void wayl_win_destroy(struct wl_window *win); + +bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale); From 98f3ccfe79b37122f879174e315df407e7f4e09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Jul 2020 20:04:02 +0200 Subject: [PATCH 09/20] wayland: log: be clear that these are the XCRUSOR_* environment variables --- wayland.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 667ae2da..99c6058a 100644 --- a/wayland.c +++ b/wayland.c @@ -912,8 +912,7 @@ wayl_init(const struct config *conf, struct fdm *fdm) } } - LOG_INFO("cursor theme: %s, size: %u", - wayl->xcursor_theme, wayl->xcursor_size); + LOG_INFO("XCURSOR_THEME=%s, XCURSOR_SIZE=%u", wayl->xcursor_theme, wayl->xcursor_size); if (!fdm_hook_add(fdm, &fdm_hook, wayl, FDM_HOOK_PRIORITY_LOW)) { LOG_ERR("failed to add FDM hook"); From fc9fde88c3ea2f9a5d4923229df146d3b96bab9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 08:46:25 +0200 Subject: [PATCH 10/20] input: only call term_kbd_focus_{in,out}() on actual state change That is, only call term_kbd_focus_in() if we're the *first* seat focusing that terminal, and only call term_kbd_focus_out() if we're the *last* seat that focused it. --- input.c | 27 ++++++++++++++++++++------- terminal.c | 4 ++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/input.c b/input.c index ea344c99..660f359e 100644 --- a/input.c +++ b/input.c @@ -304,10 +304,19 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, LOG_DBG("keyboard_enter: keyboard=%p, serial=%u, surface=%p", wl_keyboard, serial, surface); + bool term_already_focused = false; + tll_foreach(seat->wayl->seats, it) { + if (it->item.kbd_focus == term) { + term_already_focused = true; + break; + } + } + seat->kbd_focus = term; seat->input_serial = serial; - term_kbd_focus_in(seat->kbd_focus); + if (!term_already_focused) + term_kbd_focus_in(seat->kbd_focus); } static bool @@ -371,15 +380,19 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, seat->kbd_focus = NULL; stop_repeater(seat, -1); - seat->kbd.shift = false;; - seat->kbd.alt = false;; - seat->kbd.ctrl = false;; - seat->kbd.meta = false;; + seat->kbd.shift = false; + seat->kbd.alt = false; + seat->kbd.ctrl = false; + seat->kbd.meta = false; xkb_compose_state_reset(seat->kbd.xkb_compose_state); - if (old_focused != NULL) + if (old_focused != NULL) { + /* Tell term it's unfocused *if* no other seats still have it focused */ + tll_foreach(seat->wayl->seats, it) + if (it->item.kbd_focus == old_focused) + return; term_kbd_focus_out(old_focused); - else { + } else { /* * Sway bug - under certain conditions we get a * keyboard_leave() (and keyboard_key()) without first having diff --git a/terminal.c b/terminal.c index e4197a2a..fa1816ae 100644 --- a/terminal.c +++ b/terminal.c @@ -1964,6 +1964,8 @@ term_has_kbd_focus(struct terminal *term) void term_kbd_focus_in(struct terminal *term) { + assert(term_has_kbd_focus(term)); + if (term->focus_events) term_to_slave(term, "\033[I", 3); } @@ -1971,6 +1973,8 @@ term_kbd_focus_in(struct terminal *term) void term_kbd_focus_out(struct terminal *term) { + assert(!term_has_kbd_focus(term)); + if (term->focus_events) term_to_slave(term, "\033[O", 3); } From b6342bb36d83054968a1d413ccf983f6ffc0366c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 08:47:56 +0200 Subject: [PATCH 11/20] wayland: globals: destroy: handle seats being destroyed --- wayland.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 99c6058a..3567ac5f 100644 --- a/wayland.c +++ b/wayland.c @@ -827,7 +827,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) struct wayland *wayl = data; - /* For now, we only support removal of outputs */ + /* Check if this is an output */ tll_foreach(wayl->monitors, it) { struct monitor *mon = &it->item; @@ -844,11 +844,48 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) tll_foreach(wayl->terms, t) surface_leave(t->item->window, NULL /* wl_surface - unused */, mon->output); - monitor_destroy(&it->item); + monitor_destroy(mon); tll_remove(wayl->monitors, it); return; } + /* A seat? */ + tll_foreach(wayl->seats, it) { + struct seat *seat = &it->item; + + if (seat->wl_name != name) + continue; + + LOG_INFO("seat destroyed: %s", seat->name); + + if (seat->kbd_focus != NULL) { + + struct terminal *term = seat->kbd_focus; + + /* Clear this seat's focus */ + seat->kbd_focus = NULL; + + /* Check if term is focused by *another* seat */ + bool term_has_other_focus = false; + tll_foreach(wayl->seats, s) { + if (&s->item == seat) + continue; + + if (s->item.kbd_focus == term) { + term_has_other_focus = true; + break; + } + } + + /* No other seat has it focused - tell it it was unfocused */ + if (!term_has_other_focus) + term_kbd_focus_out(term); + } + + seat_destroy(seat); + tll_remove(wayl->seats, it); + } + LOG_WARN("unknown global removed: 0x%08x", name); } From a6da07b3dd8771ecf9bb2cfb3149506525e1ef53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 08:52:39 +0200 Subject: [PATCH 12/20] wayland: globals: destroy: seat: use keyboard/pointer listener interfaces --- wayland.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/wayland.c b/wayland.c index 3567ac5f..38ef57f0 100644 --- a/wayland.c +++ b/wayland.c @@ -859,27 +859,19 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) LOG_INFO("seat destroyed: %s", seat->name); if (seat->kbd_focus != NULL) { + LOG_WARN("compositor destroyed seat '%s' " + "without sending keyboard/pointer leave events", + seat->name); struct terminal *term = seat->kbd_focus; - /* Clear this seat's focus */ - seat->kbd_focus = NULL; + if (seat->wl_keyboard != NULL) + keyboard_listener.leave( + seat, seat->wl_keyboard, -1, term->window->surface); - /* Check if term is focused by *another* seat */ - bool term_has_other_focus = false; - tll_foreach(wayl->seats, s) { - if (&s->item == seat) - continue; - - if (s->item.kbd_focus == term) { - term_has_other_focus = true; - break; - } - } - - /* No other seat has it focused - tell it it was unfocused */ - if (!term_has_other_focus) - term_kbd_focus_out(term); + if (seat->wl_pointer != NULL) + pointer_listener.leave( + seat, seat->wl_pointer, -1, term->window->surface); } seat_destroy(seat); From 6bbd4a5110c148841e73efd4786ebae1c335ef80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 09:16:54 +0200 Subject: [PATCH 13/20] focus in/out: terminal checks whether it is a state change or not --- input.c | 20 +++----------------- terminal.c | 6 ++++-- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/input.c b/input.c index 660f359e..1caf46b3 100644 --- a/input.c +++ b/input.c @@ -304,19 +304,9 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, LOG_DBG("keyboard_enter: keyboard=%p, serial=%u, surface=%p", wl_keyboard, serial, surface); - bool term_already_focused = false; - tll_foreach(seat->wayl->seats, it) { - if (it->item.kbd_focus == term) { - term_already_focused = true; - break; - } - } - + term_kbd_focus_in(term); seat->kbd_focus = term; seat->input_serial = serial; - - if (!term_already_focused) - term_kbd_focus_in(seat->kbd_focus); } static bool @@ -386,13 +376,9 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, seat->kbd.meta = false; xkb_compose_state_reset(seat->kbd.xkb_compose_state); - if (old_focused != NULL) { - /* Tell term it's unfocused *if* no other seats still have it focused */ - tll_foreach(seat->wayl->seats, it) - if (it->item.kbd_focus == old_focused) - return; + if (old_focused != NULL) term_kbd_focus_out(old_focused); - } else { + else { /* * Sway bug - under certain conditions we get a * keyboard_leave() (and keyboard_key()) without first having diff --git a/terminal.c b/terminal.c index fa1816ae..96c83644 100644 --- a/terminal.c +++ b/terminal.c @@ -1964,7 +1964,8 @@ term_has_kbd_focus(struct terminal *term) void term_kbd_focus_in(struct terminal *term) { - assert(term_has_kbd_focus(term)); + if (term_has_kbd_focus(term)) + return; if (term->focus_events) term_to_slave(term, "\033[I", 3); @@ -1973,7 +1974,8 @@ term_kbd_focus_in(struct terminal *term) void term_kbd_focus_out(struct terminal *term) { - assert(!term_has_kbd_focus(term)); + if (term_has_kbd_focus(term)) + return; if (term->focus_events) term_to_slave(term, "\033[O", 3); From 3397e735a5eb5b99123152dae2bcc8611947a064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 09:17:42 +0200 Subject: [PATCH 14/20] changelog: add multi-seat support --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85f6187..1e931cca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * **blink** option to `footrc`; a boolean that lets you control whether the cursor should blink or not by default. Note that applications can override this. +* Multi-seat support ### Changed From 699cbaf3804efc75d896c1aae6c06779a4a1abf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 09:18:18 +0200 Subject: [PATCH 15/20] readme: add multi-seat support to the feature list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 62b9b964..3f628269 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ The fast, lightweight and minimalistic Wayland terminal emulator. * Scrollback search * Color emoji support * Server/daemon mode (one master process, many windows) +* Multi-seat * [Synchronized Updates](https://gitlab.freedesktop.org/terminal-wg/specifications/-/merge_requests/2) support * [Sixel image support](https://en.wikipedia.org/wiki/Sixel) From 4e48d550efba98ebecf4b60045004e52c585c52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 09:52:11 +0200 Subject: [PATCH 16/20] multi-seat: improve handling of multiple (mouse) pointers * xcursor always set for all pointers * xcursor sometimes not updated when it should be * mouse grabbed state wasn't per seat, but global (i.e. "does at least one seat enable mouse grabbing") * selection enabled state wasn't per seat --- input.c | 71 ++++++++++++++++++++++++++++------------------------- render.c | 34 ++++++++++++------------- render.h | 2 +- selection.c | 4 +-- selection.h | 2 +- terminal.c | 55 ++++++++++++++++++----------------------- terminal.h | 15 +++++++++-- wayland.h | 4 +-- 8 files changed, 97 insertions(+), 90 deletions(-) diff --git a/input.c b/input.c index 1caf46b3..f0024a0d 100644 --- a/input.c +++ b/input.c @@ -817,14 +817,14 @@ is_bottom_right(const struct terminal *term, int x, int y) static const char * xcursor_for_csd_border(struct terminal *term, int x, int y) { - if (is_top_left(term, x, y)) return "top_left_corner"; - else if (is_top_right(term, x, y)) return "top_right_corner"; - else if (is_bottom_left(term, x, y)) return "bottom_left_corner"; - else if (is_bottom_right(term, x, y)) return "bottom_right_corner"; - else if (term->active_surface == TERM_SURF_BORDER_LEFT) return "left_side"; - else if (term->active_surface == TERM_SURF_BORDER_RIGHT) return "right_side"; - else if (term->active_surface == TERM_SURF_BORDER_TOP) return "top_side"; - else if (term->active_surface == TERM_SURF_BORDER_BOTTOM) return"bottom_side"; + if (is_top_left(term, x, y)) return XCURSOR_TOP_LEFT_CORNER; + else if (is_top_right(term, x, y)) return XCURSOR_TOP_RIGHT_CORNER; + else if (is_bottom_left(term, x, y)) return XCURSOR_BOTTOM_LEFT_CORNER; + else if (is_bottom_right(term, x, y)) return XCURSOR_BOTTOM_RIGHT_CORNER; + else if (term->active_surface == TERM_SURF_BORDER_LEFT) return XCURSOR_LEFT_SIDE; + else if (term->active_surface == TERM_SURF_BORDER_RIGHT) return XCURSOR_RIGHT_SIDE; + else if (term->active_surface == TERM_SURF_BORDER_TOP) return XCURSOR_TOP_SIDE; + else if (term->active_surface == TERM_SURF_BORDER_BOTTOM) return XCURSOR_BOTTOM_SIDE; else { assert(false); return NULL; @@ -862,23 +862,20 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_SEARCH: case TERM_SURF_TITLE: - term->xcursor = "left_ptr"; - render_xcursor_set(seat, term); + render_xcursor_set(seat, term, XCURSOR_LEFT_PTR); break; case TERM_SURF_BORDER_LEFT: case TERM_SURF_BORDER_RIGHT: case TERM_SURF_BORDER_TOP: case TERM_SURF_BORDER_BOTTOM: - term->xcursor = xcursor_for_csd_border(term, x, y); - render_xcursor_set(seat, term); + render_xcursor_set(seat, term, xcursor_for_csd_border(term, x, y)); break; case TERM_SURF_BUTTON_MINIMIZE: case TERM_SURF_BUTTON_MAXIMIZE: case TERM_SURF_BUTTON_CLOSE: - term->xcursor = "left_ptr"; - render_xcursor_set(seat, term); + render_xcursor_set(seat, term, XCURSOR_LEFT_PTR); render_refresh_csd(term); break; @@ -903,7 +900,7 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, /* A cursor frame callback may never be called if the pointer leaves our surface */ wl_callback_destroy(seat->pointer.xcursor_callback); seat->pointer.xcursor_callback = NULL; - seat->pointer.pending_terminal = NULL; + seat->pointer.xcursor_pending = false; seat->pointer.xcursor = NULL; } @@ -995,8 +992,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_BORDER_RIGHT: case TERM_SURF_BORDER_TOP: case TERM_SURF_BORDER_BOTTOM: - term->xcursor = xcursor_for_csd_border(term, x, y); - render_xcursor_set(seat, term); + render_xcursor_set(seat, term, xcursor_for_csd_border(term, x, y)); break; case TERM_SURF_GRID: { @@ -1021,9 +1017,11 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (update_selection && !update_selection_early) selection_update(term, col, row); - term_mouse_motion( - term, seat->mouse.button, seat->mouse.row, seat->mouse.col, - seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + if (!term_mouse_grabbed(term, seat)) { + term_mouse_motion( + term, seat->mouse.button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + } break; } } @@ -1190,7 +1188,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (button == BTN_LEFT && seat->mouse.count <= 3) { selection_cancel(term); - if (selection_enabled(term)) { + if (selection_enabled(term, seat)) { switch (seat->mouse.count) { case 1: selection_start( @@ -1212,7 +1210,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } else if (button == BTN_RIGHT && seat->mouse.count == 1) { - if (selection_enabled(term)) { + if (selection_enabled(term, seat)) { selection_extend( seat, term, seat->mouse.col, seat->mouse.row, serial); } @@ -1238,9 +1236,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } } - term_mouse_down( - term, button, seat->mouse.row, seat->mouse.col, - seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + if (!term_mouse_grabbed(term, seat)) { + term_mouse_down( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + } break; } @@ -1248,9 +1248,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (button == BTN_LEFT && term->selection.end.col != -1) selection_finalize(seat, term, serial); - term_mouse_up( - term, button, seat->mouse.row, seat->mouse.col, - seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + if (!term_mouse_grabbed(term, seat)) { + term_mouse_up( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + } break; } break; @@ -1298,15 +1300,16 @@ mouse_scroll(struct seat *seat, int amount) keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_DOWN); keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_UP); } else { - for (int i = 0; i < amount; i++) { - term_mouse_down( + if (!term_mouse_grabbed(term, seat)) { + for (int i = 0; i < amount; i++) { + term_mouse_down( + term, button, seat->mouse.row, seat->mouse.col, + seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); + } + term_mouse_up( term, button, seat->mouse.row, seat->mouse.col, seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); } - term_mouse_up( - term, button, seat->mouse.row, seat->mouse.col, - seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); - scrollback(term, amount); } } diff --git a/render.c b/render.c index 8fb0fd6f..603f9c2d 100644 --- a/render.c +++ b/render.c @@ -1946,22 +1946,22 @@ static const struct wl_callback_listener xcursor_listener = { }; static void -render_xcursor_update(struct seat *seat, const struct terminal *term) +render_xcursor_update(struct seat *seat) { /* If called from a frame callback, we may no longer have mouse focus */ - if (seat->mouse_focus != term) + if (!seat->mouse_focus) return; - seat->pointer.cursor = wl_cursor_theme_get_cursor(seat->pointer.theme, term->xcursor); + seat->pointer.cursor = wl_cursor_theme_get_cursor( + seat->pointer.theme, seat->pointer.xcursor); + if (seat->pointer.cursor == NULL) { LOG_ERR("%s: failed to load xcursor pointer '%s'", - seat->pointer.theme_name, term->xcursor); + seat->pointer.theme_name, seat->pointer.xcursor); return; } - seat->pointer.xcursor = term->xcursor; - - const int scale = term->scale; + const int scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; wl_surface_attach( @@ -1993,9 +1993,9 @@ xcursor_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_ wl_callback_destroy(wl_callback); seat->pointer.xcursor_callback = NULL; - if (seat->pointer.pending_terminal != NULL) { - render_xcursor_update(seat, seat->pointer.pending_terminal); - seat->pointer.pending_terminal = NULL; + if (seat->pointer.xcursor_pending) { + render_xcursor_update(seat); + seat->pointer.xcursor_pending = false; } } @@ -2061,10 +2061,10 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) } tll_foreach(wayl->seats, it) { - if (it->item.pointer.pending_terminal != NULL) { + if (it->item.pointer.xcursor_pending) { if (it->item.pointer.xcursor_callback == NULL) { - render_xcursor_update(&it->item, it->item.pointer.pending_terminal); - it->item.pointer.pending_terminal = NULL; + render_xcursor_update(&it->item); + it->item.pointer.xcursor_pending = false; } else { /* Frame callback will call render_xcursor_update() */ } @@ -2099,14 +2099,13 @@ render_refresh_search(struct terminal *term) } bool -render_xcursor_set(struct seat *seat, struct terminal *term) +render_xcursor_set(struct seat *seat, struct terminal *term, const char *xcursor) { if (seat->pointer.theme == NULL) return false; if (seat->mouse_focus == NULL) { seat->pointer.xcursor = NULL; - seat->pointer.pending_terminal = NULL; return true; } @@ -2115,10 +2114,11 @@ render_xcursor_set(struct seat *seat, struct terminal *term) return true; } - if (seat->pointer.xcursor == term->xcursor) + if (seat->pointer.xcursor == xcursor) return true; /* FDM hook takes care of actual rendering */ - seat->pointer.pending_terminal = term; + seat->pointer.xcursor_pending = true; + seat->pointer.xcursor = xcursor; return true; } diff --git a/render.h b/render.h index 4640145b..05c79322 100644 --- a/render.h +++ b/render.h @@ -16,7 +16,7 @@ void render_refresh(struct terminal *term); void render_refresh_csd(struct terminal *term); void render_refresh_search(struct terminal *term); void render_refresh_title(struct terminal *term); -bool render_xcursor_set(struct seat *seat, struct terminal *term); +bool render_xcursor_set(struct seat *seat, struct terminal *term, const char *xcursor); struct render_worker_context { int my_id; diff --git a/selection.c b/selection.c index 2c8176dd..f097e37b 100644 --- a/selection.c +++ b/selection.c @@ -21,11 +21,11 @@ #include "vt.h" bool -selection_enabled(const struct terminal *term) +selection_enabled(const struct terminal *term, struct seat *seat) { return term->mouse_tracking == MOUSE_NONE || - term_mouse_grabbed(term) || + term_mouse_grabbed(term, seat) || term->is_searching; } diff --git a/selection.h b/selection.h index e049f182..52b0f1a3 100644 --- a/selection.h +++ b/selection.h @@ -8,7 +8,7 @@ extern const struct wl_data_device_listener data_device_listener; extern const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener; -bool selection_enabled(const struct terminal *term); +bool selection_enabled(const struct terminal *term, struct seat *seat); void selection_start( struct terminal *term, int col, int row, enum selection_kind kind); void selection_update(struct terminal *term, int col, int row); diff --git a/terminal.c b/terminal.c index 96c83644..1e7ddabe 100644 --- a/terminal.c +++ b/terminal.c @@ -34,9 +34,17 @@ #define PTMX_TIMING 0 -static const char *const XCURSOR_LEFT_PTR = "left_ptr"; -static const char *const XCURSOR_TEXT = "text"; -//static const char *const XCURSOR_HAND2 = "hand2"; +const char *const XCURSOR_LEFT_PTR = "left_ptr"; +const char *const XCURSOR_TEXT = "text"; +//const char *const XCURSOR_HAND2 = "hand2"; +const char *const XCURSOR_TOP_LEFT_CORNER = "top_left_corner"; +const char *const XCURSOR_TOP_RIGHT_CORNER = "top_right_corner"; +const char *const XCURSOR_BOTTOM_LEFT_CORNER = "bottom_left_corner"; +const char *const XCURSOR_BOTTOM_RIGHT_CORNER = "bottom_right_corner"; +const char *const XCURSOR_LEFT_SIDE = "left_side"; +const char *const XCURSOR_RIGHT_SIDE = "right_side"; +const char *const XCURSOR_TOP_SIDE = "top_side"; +const char *const XCURSOR_BOTTOM_SIDE = "bottom_side"; bool term_to_slave(struct terminal *term, const void *_data, size_t len) @@ -889,7 +897,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .text = conf->cursor.color.text, .cursor = conf->cursor.color.cursor, }, - .xcursor = "text", .selection = { .start = {-1, -1}, .end = {-1, -1}, @@ -2068,31 +2075,20 @@ report_mouse_motion(struct terminal *term, int encoded_button, int row, int col) } bool -term_mouse_grabbed(const struct terminal *term) +term_mouse_grabbed(const struct terminal *term, struct seat *seat) { /* * Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not. */ - tll_foreach(term->wl->seats, it) { - const struct seat *seat = &it->item; - - if (seat->kbd_focus == term && - seat->kbd.shift && - !seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.meta) - { - return true; - } - } - return false; + return seat->kbd_focus == term && + seat->kbd.shift && + !seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.meta; } void term_mouse_down(struct terminal *term, int button, int row, int col, bool _shift, bool _alt, bool _ctrl) { - if (term_mouse_grabbed(term)) - return; - /* Map libevent button event code to X button number */ int xbutton = linux_mouse_button_to_x(button); if (xbutton == -1) @@ -2131,9 +2127,6 @@ void term_mouse_up(struct terminal *term, int button, int row, int col, bool _shift, bool _alt, bool _ctrl) { - if (term_mouse_grabbed(term)) - return; - /* Map libevent button event code to X button number */ int xbutton = linux_mouse_button_to_x(button); if (xbutton == -1) @@ -2176,9 +2169,6 @@ void term_mouse_motion(struct terminal *term, int button, int row, int col, bool _shift, bool _alt, bool _ctrl) { - if (term_mouse_grabbed(term)) - return; - int encoded = 0; if (button != 0) { @@ -2225,13 +2215,16 @@ term_mouse_motion(struct terminal *term, int button, int row, int col, void term_xcursor_update(struct terminal *term) { - term->xcursor = - term->is_searching ? XCURSOR_LEFT_PTR : /* TODO: something different? */ - selection_enabled(term) ? XCURSOR_TEXT : - XCURSOR_LEFT_PTR; + tll_foreach(term->wl->seats, it) { + struct seat *seat = &it->item; - tll_foreach(term->wl->seats, it) - render_xcursor_set(&it->item, term); + const char *xcursor + = term->is_searching ? XCURSOR_LEFT_PTR : /* TODO: something different? */ + selection_enabled(term, seat) ? XCURSOR_TEXT : + XCURSOR_LEFT_PTR; + + render_xcursor_set(seat, term, xcursor); + } } void diff --git a/terminal.h b/terminal.h index 604511da..8316795f 100644 --- a/terminal.h +++ b/terminal.h @@ -305,7 +305,6 @@ struct terminal { uint32_t text; uint32_t cursor; } cursor_color; - const char *xcursor; struct { enum selection_kind kind; @@ -439,6 +438,18 @@ struct terminal { char *cwd; }; +extern const char *const XCURSOR_LEFT_PTR; +extern const char *const XCURSOR_TEXT; +//extern const char *const XCURSOR_HAND2; +extern const char *const XCURSOR_TOP_LEFT_CORNER; +extern const char *const XCURSOR_TOP_RIGHT_CORNER; +extern const char *const XCURSOR_BOTTOM_LEFT_CORNER; +extern const char *const XCURSOR_BOTTOM_RIGHT_CORNER; +extern const char *const XCURSOR_LEFT_SIDE; +extern const char *const XCURSOR_RIGHT_SIDE; +extern const char *const XCURSOR_TOP_SIDE; +extern const char *const XCURSOR_BOTTOM_SIDE; + struct config; struct terminal *term_init( const struct config *conf, struct fdm *fdm, struct reaper *reaper, @@ -518,7 +529,7 @@ void term_mouse_up( void term_mouse_motion( struct terminal *term, int button, int row, int col, bool shift, bool alt, bool ctrl); -bool term_mouse_grabbed(const struct terminal *term); +bool term_mouse_grabbed(const struct terminal *term, struct seat *seat); void term_xcursor_update(struct terminal *term); void term_set_window_title(struct terminal *term, const char *title); diff --git a/wayland.h b/wayland.h index 489f485d..f703883e 100644 --- a/wayland.h +++ b/wayland.h @@ -148,10 +148,10 @@ struct seat { int size; int scale; char *theme_name; - const char *xcursor; - const struct terminal *pending_terminal; + const char *xcursor; struct wl_callback *xcursor_callback; + bool xcursor_pending; } pointer; struct { From 71584aed388935908588686e5df7ec42855f3698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 9 Jul 2020 11:20:46 +0200 Subject: [PATCH 17/20] seat: use separate 'enter' serials for keyboard and mouse --- input.c | 10 ++++++---- osc.c | 7 +++---- selection.c | 4 ++-- selection.h | 2 +- wayland.h | 3 ++- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/input.c b/input.c index f0024a0d..bc35ad56 100644 --- a/input.c +++ b/input.c @@ -306,7 +306,7 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, term_kbd_focus_in(term); seat->kbd_focus = term; - seat->input_serial = serial; + seat->kbd.serial = serial; } static bool @@ -773,7 +773,7 @@ const struct wl_keyboard_listener keyboard_listener = { void input_repeat(struct seat *seat, uint32_t key) { - keyboard_key(seat, NULL, seat->input_serial, 0, key, XKB_KEY_DOWN); + keyboard_key(seat, NULL, seat->kbd.serial, 0, key, XKB_KEY_DOWN); } static bool @@ -842,6 +842,8 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, struct wl_window *win = wl_surface_get_user_data(surface); struct terminal *term = win->term; + seat->pointer.serial = serial; + LOG_DBG("pointer-enter: pointer=%p, serial=%u, surface = %p, new-moused = %p", wl_pointer, serial, surface, term); @@ -1297,8 +1299,8 @@ mouse_scroll(struct seat *seat, int amount) xkb_keycode_t key = button == BTN_BACK ? key_arrow_up : key_arrow_down; for (int i = 0; i < amount; i++) - keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_DOWN); - keyboard_key(seat, NULL, seat->input_serial, 0, key - 8, XKB_KEY_UP); + keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN); + keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_UP); } else { if (!term_mouse_grabbed(term, seat)) { for (int i = 0; i < amount; i++) { diff --git a/osc.c b/osc.c index 3183f196..42bef722 100644 --- a/osc.c +++ b/osc.c @@ -68,13 +68,13 @@ osc_to_clipboard(struct terminal *term, const char *target, if (to_clipboard) { char *copy = strdup(decoded); - if (!text_to_clipboard(seat, term, copy, seat->input_serial)) + if (!text_to_clipboard(seat, term, copy, seat->kbd.serial)) free(copy); } if (to_primary) { char *copy = strdup(decoded); - if (!text_to_primary(seat, term, copy, seat->input_serial)) + if (!text_to_primary(seat, term, copy, seat->kbd.serial)) free(copy); } @@ -190,8 +190,7 @@ osc_from_clipboard(struct terminal *term, const char *source) switch (src) { case 'c': text_from_clipboard( - seat, term, seat->input_serial, - &from_clipboard_cb, &from_clipboard_done, ctx); + seat, term, &from_clipboard_cb, &from_clipboard_done, ctx); break; case 's': diff --git a/selection.c b/selection.c index f097e37b..62f131b1 100644 --- a/selection.c +++ b/selection.c @@ -1087,7 +1087,7 @@ begin_receive_clipboard(struct terminal *term, int read_fd, } void -text_from_clipboard(struct seat *seat, struct terminal *term, uint32_t serial, +text_from_clipboard(struct seat *seat, struct terminal *term, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user) { @@ -1142,7 +1142,7 @@ selection_from_clipboard(struct seat *seat, struct terminal *term, uint32_t seri term_to_slave(term, "\033[200~", 6); text_from_clipboard( - seat, term, serial, &from_clipboard_cb, &from_clipboard_done, term); + seat, term, &from_clipboard_cb, &from_clipboard_done, term); } bool diff --git a/selection.h b/selection.h index 52b0f1a3..bd995855 100644 --- a/selection.h +++ b/selection.h @@ -59,7 +59,7 @@ bool text_to_primary( * point). */ void text_from_clipboard( - struct seat *seat, struct terminal *term, uint32_t serial, + struct seat *seat, struct terminal *term, void (*cb)(const char *data, size_t size, void *user), void (*done)(void *user), void *user); diff --git a/wayland.h b/wayland.h index f703883e..0b136c04 100644 --- a/wayland.h +++ b/wayland.h @@ -106,6 +106,8 @@ struct seat { /* Keyboard state */ struct wl_keyboard *wl_keyboard; struct { + uint32_t serial; + struct xkb_context *xkb; struct xkb_keymap *xkb_keymap; struct xkb_state *xkb_state; @@ -171,7 +173,6 @@ struct seat { } mouse; /* Clipboard */ - uint32_t input_serial; struct wl_data_device *data_device; struct zwp_primary_selection_device_v1 *primary_selection_device; From bf62519d8330204b12e9e3743fb332e3abde0ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 10 Jul 2020 12:06:55 +0200 Subject: [PATCH 18/20] wayland: read XCURSOR_{THEME,SIZE} in reload_xcursor theme --- render.c | 3 +-- wayland.c | 42 +++++++++++++++--------------------------- wayland.h | 5 ----- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/render.c b/render.c index 603f9c2d..670b9282 100644 --- a/render.c +++ b/render.c @@ -1956,8 +1956,7 @@ render_xcursor_update(struct seat *seat) seat->pointer.theme, seat->pointer.xcursor); if (seat->pointer.cursor == NULL) { - LOG_ERR("%s: failed to load xcursor pointer '%s'", - seat->pointer.theme_name, seat->pointer.xcursor); + LOG_ERR("failed to load xcursor pointer '%s'", seat->pointer.xcursor); return; } diff --git a/wayland.c b/wayland.c index 38ef57f0..2ba385fa 100644 --- a/wayland.c +++ b/wayland.c @@ -96,7 +96,6 @@ seat_destroy(struct seat *seat) if (seat->kbd.repeat.fd >= 0) fdm_del(seat->wayl->fdm, seat->kbd.repeat.fd); - free(seat->pointer.theme_name); if (seat->pointer.theme != NULL) wl_cursor_theme_destroy(seat->pointer.theme); if (seat->pointer.surface != NULL) @@ -718,8 +717,6 @@ handle_global(void *data, struct wl_registry *registry, }, .pointer = { .surface = pointer_surf, - .size = wayl->xcursor_size, - .theme_name = wayl->xcursor_theme != NULL ? strdup(wayl->xcursor_theme) : NULL, }, .data_device = data_device, .primary_selection_device = primary_selection_device, @@ -926,23 +923,6 @@ wayl_init(const struct config *conf, struct fdm *fdm) wayl->fdm = fdm; wayl->fd = -1; - /* XCursor */ - const char *xcursor_theme = getenv("XCURSOR_THEME"); - if (xcursor_theme != NULL) - wayl->xcursor_theme = strdup(xcursor_theme); - wayl->xcursor_size = 24; - - { - const char *env_cursor_size = getenv("XCURSOR_SIZE"); - if (env_cursor_size != NULL) { - unsigned size; - if (sscanf(env_cursor_size, "%u", &size) == 1) - wayl->xcursor_size = size; - } - } - - LOG_INFO("XCURSOR_THEME=%s, XCURSOR_SIZE=%u", wayl->xcursor_theme, wayl->xcursor_size); - if (!fdm_hook_add(fdm, &fdm_hook, wayl, FDM_HOOK_PRIORITY_LOW)) { LOG_ERR("failed to add FDM hook"); goto out; @@ -1085,7 +1065,6 @@ wayl_destroy(struct wayland *wayl) if (wayl->display != NULL) wl_display_disconnect(wayl->display); - free(wayl->xcursor_theme); free(wayl); } @@ -1223,9 +1202,6 @@ wayl_win_destroy(struct wl_window *win) bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale) { - if (seat->pointer.size == 0) - return true; - if (seat->pointer.theme != NULL && seat->pointer.scale == new_scale) { /* We already have a theme loaded, and the scale hasn't changed */ return true; @@ -1238,11 +1214,23 @@ wayl_reload_xcursor_theme(struct seat *seat, int new_scale) seat->pointer.cursor = NULL; } - LOG_DBG("reloading cursor theme: %s@%d", - seat->pointer.theme_name, seat->pointer.size); + const char *xcursor_theme = getenv("XCURSOR_THEME"); + int xcursor_size = 24; + + { + const char *env_cursor_size = getenv("XCURSOR_SIZE"); + if (env_cursor_size != NULL) { + unsigned size; + if (sscanf(env_cursor_size, "%u", &size) == 1) + xcursor_size = size; + } + } + + LOG_INFO("cursor theme: %s, size: %u, scale: %d", + xcursor_theme, xcursor_size, new_scale); seat->pointer.theme = wl_cursor_theme_load( - seat->pointer.theme_name, seat->pointer.size * new_scale, seat->wayl->shm); + xcursor_theme, xcursor_size * new_scale, seat->wayl->shm); if (seat->pointer.theme == NULL) { LOG_ERR("failed to load cursor theme"); diff --git a/wayland.h b/wayland.h index 0b136c04..224853a6 100644 --- a/wayland.h +++ b/wayland.h @@ -147,9 +147,7 @@ struct seat { struct wl_surface *surface; struct wl_cursor_theme *theme; struct wl_cursor *cursor; - int size; int scale; - char *theme_name; const char *xcursor; struct wl_callback *xcursor_callback; @@ -318,9 +316,6 @@ struct wayland { tll(struct seat) seats; tll(struct terminal *) terms; - - char *xcursor_theme; - unsigned xcursor_size; }; struct wayland *wayl_init(const struct config *conf, struct fdm *fdm); From 5677df629e4323c8e8ca24d11dd63725934a4c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 10 Jul 2020 19:24:33 +0200 Subject: [PATCH 19/20] wayland: seat: instantiate pointer surface in capabilities event This way we only instantiate the surface for seats that actually have a pointer. --- wayland.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/wayland.c b/wayland.c index 2ba385fa..9a6df83b 100644 --- a/wayland.c +++ b/wayland.c @@ -176,13 +176,25 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, if (caps & WL_SEAT_CAPABILITY_POINTER) { if (seat->wl_pointer == NULL) { + assert(seat->pointer.surface == NULL); + seat->pointer.surface = wl_compositor_create_surface(seat->wayl->compositor); + + if (seat->pointer.surface == NULL) { + LOG_ERR("%s: failed to create pointer surface", seat->name); + return; + } + seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } } else { if (seat->wl_pointer != NULL) { wl_pointer_release(seat->wl_pointer); + wl_surface_destroy(seat->pointer.surface); + seat->wl_pointer = NULL; + seat->pointer.surface = NULL; + seat->pointer.cursor = NULL; } } } @@ -703,9 +715,6 @@ handle_global(void *data, struct wl_registry *registry, } else primary_selection_device = NULL; - struct wl_surface *pointer_surf - = wl_compositor_create_surface(wayl->compositor); - tll_push_back(wayl->seats, ((struct seat){ .wayl = wayl, .wl_seat = wl_seat, @@ -715,9 +724,6 @@ handle_global(void *data, struct wl_registry *registry, .fd = repeat_fd, }, }, - .pointer = { - .surface = pointer_surf, - }, .data_device = data_device, .primary_selection_device = primary_selection_device, })); From 1c13061f35b2d826bee931dee2a00d911173a946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 10 Jul 2020 19:32:48 +0200 Subject: [PATCH 20/20] wayland: destroy cursor theme when removing pointer capability --- wayland.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wayland.c b/wayland.c index 9a6df83b..1320fc3a 100644 --- a/wayland.c +++ b/wayland.c @@ -192,8 +192,12 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_pointer_release(seat->wl_pointer); wl_surface_destroy(seat->pointer.surface); + if (seat->pointer.theme != NULL) + wl_cursor_theme_destroy(seat->pointer.theme); + seat->wl_pointer = NULL; seat->pointer.surface = NULL; + seat->pointer.theme = NULL; seat->pointer.cursor = NULL; } }