You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1795 lines
60 KiB

  1. #include "input.h"
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <signal.h>
  5. #include <threads.h>
  6. #include <locale.h>
  7. #include <errno.h>
  8. #include <sys/mman.h>
  9. #include <sys/time.h>
  10. #include <sys/timerfd.h>
  11. #include <sys/epoll.h>
  12. #include <fcntl.h>
  13. #include <linux/input-event-codes.h>
  14. #include <xkbcommon/xkbcommon.h>
  15. #include <xkbcommon/xkbcommon-keysyms.h>
  16. #include <xkbcommon/xkbcommon-compose.h>
  17. #include <xdg-shell.h>
  18. #define LOG_MODULE "input"
  19. #define LOG_ENABLE_DBG 0
  20. #include "log.h"
  21. #include "config.h"
  22. #include "commands.h"
  23. #include "keymap.h"
  24. #include "macros.h"
  25. #include "quirks.h"
  26. #include "render.h"
  27. #include "search.h"
  28. #include "selection.h"
  29. #include "spawn.h"
  30. #include "terminal.h"
  31. #include "tokenize.h"
  32. #include "util.h"
  33. #include "vt.h"
  34. #include "xmalloc.h"
  35. struct pipe_context {
  36. char *text;
  37. size_t idx;
  38. size_t left;
  39. };
  40. static bool
  41. fdm_write_pipe(struct fdm *fdm, int fd, int events, void *data)
  42. {
  43. struct pipe_context *ctx = data;
  44. if (events & EPOLLHUP)
  45. goto pipe_closed;
  46. assert(events & EPOLLOUT);
  47. ssize_t written = write(fd, &ctx->text[ctx->idx], ctx->left);
  48. if (written < 0) {
  49. LOG_WARN("failed to write to pipe: %s", strerror(errno));
  50. goto pipe_closed;
  51. }
  52. assert(written <= ctx->left);
  53. ctx->idx += written;
  54. ctx->left -= written;
  55. if (ctx->left == 0)
  56. goto pipe_closed;
  57. return true;
  58. pipe_closed:
  59. free(ctx->text);
  60. free(ctx);
  61. fdm_del(fdm, fd);
  62. return true;
  63. }
  64. static bool
  65. execute_binding(struct seat *seat, struct terminal *term,
  66. enum bind_action_normal action, char *const *pipe_argv,
  67. uint32_t serial)
  68. {
  69. const bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
  70. switch (action) {
  71. case BIND_ACTION_NONE:
  72. return true;
  73. case BIND_ACTION_SCROLLBACK_UP:
  74. case BIND_ACTION_SCROLLBACK_UP_PAGE:
  75. cmd_scrollback_up(term, term->rows);
  76. return true;
  77. case BIND_ACTION_SCROLLBACK_UP_HALF_PAGE:
  78. cmd_scrollback_up(term, max(term->rows / 2, 1));
  79. return true;
  80. case BIND_ACTION_SCROLLBACK_UP_LINE:
  81. cmd_scrollback_up(term, 1);
  82. return true;
  83. case BIND_ACTION_SCROLLBACK_DOWN:
  84. case BIND_ACTION_SCROLLBACK_DOWN_PAGE:
  85. cmd_scrollback_down(term, term->rows);
  86. return true;
  87. case BIND_ACTION_SCROLLBACK_DOWN_HALF_PAGE:
  88. cmd_scrollback_down(term, max(term->rows / 2, 1));
  89. return true;
  90. case BIND_ACTION_SCROLLBACK_DOWN_LINE:
  91. cmd_scrollback_down(term, 1);
  92. return true;
  93. case BIND_ACTION_CLIPBOARD_COPY:
  94. selection_to_clipboard(seat, term, serial);
  95. return true;
  96. case BIND_ACTION_CLIPBOARD_PASTE:
  97. selection_from_clipboard(seat, term, serial);
  98. term_reset_view(term);
  99. return true;
  100. case BIND_ACTION_PRIMARY_PASTE:
  101. selection_from_primary(seat, term);
  102. return true;
  103. case BIND_ACTION_SEARCH_START:
  104. search_begin(term);
  105. return true;
  106. case BIND_ACTION_FONT_SIZE_UP:
  107. term_font_size_increase(term);
  108. return true;
  109. case BIND_ACTION_FONT_SIZE_DOWN:
  110. term_font_size_decrease(term);
  111. return true;
  112. case BIND_ACTION_FONT_SIZE_RESET:
  113. term_font_size_reset(term);
  114. return true;
  115. case BIND_ACTION_SPAWN_TERMINAL:
  116. term_spawn_new(term);
  117. return true;
  118. case BIND_ACTION_MINIMIZE:
  119. xdg_toplevel_set_minimized(term->window->xdg_toplevel);
  120. return true;
  121. case BIND_ACTION_MAXIMIZE:
  122. if (term->window->is_fullscreen)
  123. xdg_toplevel_unset_fullscreen(term->window->xdg_toplevel);
  124. if (term->window->is_maximized)
  125. xdg_toplevel_unset_maximized(term->window->xdg_toplevel);
  126. else
  127. xdg_toplevel_set_maximized(term->window->xdg_toplevel);
  128. return true;
  129. case BIND_ACTION_FULLSCREEN:
  130. if (term->window->is_fullscreen)
  131. xdg_toplevel_unset_fullscreen(term->window->xdg_toplevel);
  132. else
  133. xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL);
  134. return true;
  135. case BIND_ACTION_PIPE_SCROLLBACK:
  136. case BIND_ACTION_PIPE_VIEW:
  137. case BIND_ACTION_PIPE_SELECTED: {
  138. if (pipe_argv == NULL)
  139. return true;
  140. struct pipe_context *ctx = NULL;
  141. int pipe_fd[2] = {-1, -1};
  142. int stdout_fd = -1;
  143. int stderr_fd = -1;
  144. char *text = NULL;
  145. size_t len = 0;
  146. if (pipe(pipe_fd) < 0) {
  147. LOG_ERRNO("failed to create pipe");
  148. goto pipe_err;
  149. }
  150. stdout_fd = open("/dev/null", O_WRONLY);
  151. stderr_fd = open("/dev/null", O_WRONLY);
  152. if (stdout_fd < 0 || stderr_fd < 0) {
  153. LOG_ERRNO("failed to open /dev/null");
  154. goto pipe_err;
  155. }
  156. bool success;
  157. switch (action) {
  158. case BIND_ACTION_PIPE_SCROLLBACK:
  159. success = term_scrollback_to_text(term, &text, &len);
  160. break;
  161. case BIND_ACTION_PIPE_VIEW:
  162. success = term_view_to_text(term, &text, &len);
  163. break;
  164. case BIND_ACTION_PIPE_SELECTED:
  165. text = selection_to_text(term);
  166. success = text != NULL;
  167. len = text != NULL ? strlen(text) : 0;
  168. break;
  169. default:
  170. assert(false);
  171. success = false;
  172. break;
  173. }
  174. if (!success)
  175. goto pipe_err;
  176. /* Make write-end non-blocking; required by the FDM */
  177. {
  178. int flags = fcntl(pipe_fd[1], F_GETFL);
  179. if (flags < 0 ||
  180. fcntl(pipe_fd[1], F_SETFL, flags | O_NONBLOCK) < 0)
  181. {
  182. LOG_ERRNO("failed to make write-end of pipe non-blocking");
  183. goto pipe_err;
  184. }
  185. }
  186. /* Make sure write-end is closed on exec() - or the spawned
  187. * program may not terminate*/
  188. {
  189. int flags = fcntl(pipe_fd[1], F_GETFD);
  190. if (flags < 0 ||
  191. fcntl(pipe_fd[1], F_SETFD, flags | FD_CLOEXEC) < 0)
  192. {
  193. LOG_ERRNO("failed to set FD_CLOEXEC on writeend of pipe");
  194. goto pipe_err;
  195. }
  196. }
  197. if (!spawn(term->reaper, NULL, pipe_argv, pipe_fd[0], stdout_fd, stderr_fd))
  198. goto pipe_err;
  199. /* Close read end */
  200. close(pipe_fd[0]);
  201. ctx = xmalloc(sizeof(*ctx));
  202. *ctx = (struct pipe_context){
  203. .text = text,
  204. .left = len,
  205. };
  206. /* Asynchronously write the output to the pipe */
  207. if (!fdm_add(term->fdm, pipe_fd[1], EPOLLOUT, &fdm_write_pipe, ctx))
  208. goto pipe_err;
  209. return true;
  210. pipe_err:
  211. if (stdout_fd >= 0)
  212. close(stdout_fd);
  213. if (stderr_fd >= 0)
  214. close(stderr_fd);
  215. if (pipe_fd[0] >= 0)
  216. close(pipe_fd[0]);
  217. if (pipe_fd[1] >= 0)
  218. close(pipe_fd[1]);
  219. free(text);
  220. free(ctx);
  221. return true;
  222. }
  223. case BIND_ACTION_SELECT_BEGIN:
  224. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  225. selection_start(
  226. term, seat->mouse.col, seat->mouse.row, SELECTION_NORMAL);
  227. return true;
  228. }
  229. return false;
  230. case BIND_ACTION_SELECT_BEGIN_BLOCK:
  231. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  232. selection_start(
  233. term, seat->mouse.col, seat->mouse.row, SELECTION_BLOCK);
  234. return true;
  235. }
  236. return false;
  237. case BIND_ACTION_SELECT_EXTEND:
  238. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  239. selection_extend(
  240. seat, term, seat->mouse.col, seat->mouse.row, serial);
  241. return true;
  242. }
  243. return false;
  244. case BIND_ACTION_SELECT_WORD:
  245. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  246. selection_mark_word(
  247. seat, term, seat->mouse.col, seat->mouse.row, false, serial);
  248. return true;
  249. }
  250. return false;
  251. case BIND_ACTION_SELECT_WORD_WS:
  252. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  253. selection_mark_word(
  254. seat, term, seat->mouse.col, seat->mouse.row, true, serial);
  255. return true;
  256. }
  257. return false;
  258. case BIND_ACTION_SELECT_ROW:
  259. if (selection_enabled(term, seat) && cursor_is_on_grid) {
  260. selection_mark_row(seat, term, seat->mouse.row, serial);
  261. return true;
  262. }
  263. return false;
  264. case BIND_ACTION_COUNT:
  265. assert(false);
  266. return false;
  267. }
  268. return false;
  269. }
  270. static xkb_mod_mask_t
  271. conf_modifiers_to_mask(const struct seat *seat,
  272. const struct config_key_modifiers *modifiers)
  273. {
  274. xkb_mod_mask_t mods = 0;
  275. mods |= modifiers->shift << seat->kbd.mod_shift;
  276. mods |= modifiers->ctrl << seat->kbd.mod_ctrl;
  277. mods |= modifiers->alt << seat->kbd.mod_alt;
  278. mods |= modifiers->meta << seat->kbd.mod_meta;
  279. return mods;
  280. }
  281. static xkb_keycode_list_t
  282. key_codes_for_xkb_sym(struct xkb_keymap *keymap, xkb_keysym_t sym)
  283. {
  284. xkb_keycode_list_t key_codes = tll_init();
  285. /*
  286. * Find all key codes that map to the lower case
  287. * version of the symbol.
  288. *
  289. * This allows us to match bindings in other layouts
  290. * too.
  291. */
  292. xkb_keysym_t lower_sym = xkb_keysym_to_lower(sym);
  293. struct xkb_state *state = xkb_state_new(keymap);
  294. for (xkb_keycode_t code = xkb_keymap_min_keycode(keymap);
  295. code <= xkb_keymap_max_keycode(keymap);
  296. code++)
  297. {
  298. if (xkb_state_key_get_one_sym(state, code) == lower_sym)
  299. tll_push_back(key_codes, code);
  300. }
  301. xkb_state_unref(state);
  302. return key_codes;
  303. }
  304. static void
  305. convert_key_binding(struct seat *seat,
  306. const struct config_key_binding_normal *conf_binding)
  307. {
  308. struct key_binding_normal binding = {
  309. .action = conf_binding->action,
  310. .bind = {
  311. .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers),
  312. .sym = conf_binding->sym,
  313. .key_codes = key_codes_for_xkb_sym(
  314. seat->kbd.xkb_keymap, conf_binding->sym),
  315. },
  316. .pipe_argv = conf_binding->pipe.argv,
  317. };
  318. tll_push_back(seat->kbd.bindings.key, binding);
  319. }
  320. static void
  321. convert_key_bindings(const struct config *conf, struct seat *seat)
  322. {
  323. tll_foreach(conf->bindings.key, it)
  324. convert_key_binding(seat, &it->item);
  325. }
  326. static void
  327. convert_search_binding(struct seat *seat,
  328. const struct config_key_binding_search *conf_binding)
  329. {
  330. struct key_binding_search binding = {
  331. .action = conf_binding->action,
  332. .bind = {
  333. .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers),
  334. .sym = conf_binding->sym,
  335. .key_codes = key_codes_for_xkb_sym(
  336. seat->kbd.xkb_keymap, conf_binding->sym),
  337. },
  338. };
  339. tll_push_back(seat->kbd.bindings.search, binding);
  340. }
  341. static void
  342. convert_search_bindings(const struct config *conf, struct seat *seat)
  343. {
  344. tll_foreach(conf->bindings.search, it)
  345. convert_search_binding(seat, &it->item);
  346. }
  347. static void
  348. convert_mouse_binding(struct seat *seat,
  349. const struct config_mouse_binding *conf_binding)
  350. {
  351. struct mouse_binding binding = {
  352. .action = conf_binding->action,
  353. .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers),
  354. .button = conf_binding->button,
  355. .count = conf_binding->count,
  356. };
  357. tll_push_back(seat->mouse.bindings, binding);
  358. }
  359. static void
  360. convert_mouse_bindings(const struct config *conf, struct seat *seat)
  361. {
  362. tll_foreach(conf->bindings.mouse, it)
  363. convert_mouse_binding(seat, &it->item);
  364. }
  365. static void
  366. keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
  367. uint32_t format, int32_t fd, uint32_t size)
  368. {
  369. LOG_DBG("keyboard_keymap: keyboard=%p (format=%u, size=%u)",
  370. (void *)wl_keyboard, format, size);
  371. struct seat *seat = data;
  372. struct wayland *wayl = seat->wayl;
  373. char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
  374. if (map_str == MAP_FAILED) {
  375. LOG_ERRNO("failed to mmap keyboard keymap");
  376. close(fd);
  377. return;
  378. }
  379. while (map_str[size - 1] == '\0')
  380. size--;
  381. if (seat->kbd.xkb_compose_state != NULL) {
  382. xkb_compose_state_unref(seat->kbd.xkb_compose_state);
  383. seat->kbd.xkb_compose_state = NULL;
  384. }
  385. if (seat->kbd.xkb_compose_table != NULL) {
  386. xkb_compose_table_unref(seat->kbd.xkb_compose_table);
  387. seat->kbd.xkb_compose_table = NULL;
  388. }
  389. if (seat->kbd.xkb_keymap != NULL) {
  390. xkb_keymap_unref(seat->kbd.xkb_keymap);
  391. seat->kbd.xkb_keymap = NULL;
  392. }
  393. if (seat->kbd.xkb_state != NULL) {
  394. xkb_state_unref(seat->kbd.xkb_state);
  395. seat->kbd.xkb_state = NULL;
  396. }
  397. if (seat->kbd.xkb != NULL) {
  398. xkb_context_unref(seat->kbd.xkb);
  399. seat->kbd.xkb = NULL;
  400. }
  401. tll_foreach(seat->kbd.bindings.key, it)
  402. tll_free(it->item.bind.key_codes);
  403. tll_free(seat->kbd.bindings.key);
  404. tll_foreach(seat->kbd.bindings.search, it)
  405. tll_free(it->item.bind.key_codes);
  406. tll_free(seat->kbd.bindings.search);
  407. tll_free(seat->mouse.bindings);
  408. seat->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
  409. seat->kbd.xkb_keymap = xkb_keymap_new_from_buffer(
  410. seat->kbd.xkb, map_str, size, XKB_KEYMAP_FORMAT_TEXT_V1,
  411. XKB_KEYMAP_COMPILE_NO_FLAGS);
  412. seat->kbd.xkb_state = xkb_state_new(seat->kbd.xkb_keymap);
  413. seat->kbd.mod_shift = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Shift");
  414. seat->kbd.mod_alt = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod1") ;
  415. seat->kbd.mod_ctrl = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Control");
  416. seat->kbd.mod_meta = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod4");
  417. seat->kbd.key_arrow_up = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "UP");
  418. seat->kbd.key_arrow_down = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "DOWN");
  419. /* Compose (dead keys) */
  420. seat->kbd.xkb_compose_table = xkb_compose_table_new_from_locale(
  421. seat->kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS);
  422. seat->kbd.xkb_compose_state = xkb_compose_state_new(
  423. seat->kbd.xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
  424. munmap(map_str, size);
  425. close(fd);
  426. convert_key_bindings(wayl->conf, seat);
  427. convert_search_bindings(wayl->conf, seat);
  428. convert_mouse_bindings(wayl->conf, seat);
  429. }
  430. static void
  431. keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
  432. struct wl_surface *surface, struct wl_array *keys)
  433. {
  434. assert(surface != NULL);
  435. struct seat *seat = data;
  436. struct wl_window *win = wl_surface_get_user_data(surface);
  437. struct terminal *term = win->term;
  438. LOG_DBG("%s: keyboard_enter: keyboard=%p, serial=%u, surface=%p",
  439. seat->name, (void *)wl_keyboard, serial, (void *)surface);
  440. if (seat->kbd.xkb == NULL)
  441. return;
  442. term_kbd_focus_in(term);
  443. seat->kbd_focus = term;
  444. seat->kbd.serial = serial;
  445. }
  446. static bool
  447. start_repeater(struct seat *seat, uint32_t key)
  448. {
  449. if (seat->kbd.repeat.dont_re_repeat)
  450. return true;
  451. struct itimerspec t = {
  452. .it_value = {.tv_sec = 0, .tv_nsec = seat->kbd.repeat.delay * 1000000},
  453. .it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / seat->kbd.repeat.rate},
  454. };
  455. if (t.it_value.tv_nsec >= 1000000000) {
  456. t.it_value.tv_sec += t.it_value.tv_nsec / 1000000000;
  457. t.it_value.tv_nsec %= 1000000000;
  458. }
  459. if (t.it_interval.tv_nsec >= 1000000000) {
  460. t.it_interval.tv_sec += t.it_interval.tv_nsec / 1000000000;
  461. t.it_interval.tv_nsec %= 1000000000;
  462. }
  463. if (timerfd_settime(seat->kbd.repeat.fd, 0, &t, NULL) < 0) {
  464. LOG_ERRNO("%s: failed to arm keyboard repeat timer", seat->name);
  465. return false;
  466. }
  467. seat->kbd.repeat.key = key;
  468. return true;
  469. }
  470. static bool
  471. stop_repeater(struct seat *seat, uint32_t key)
  472. {
  473. if (key != -1 && key != seat->kbd.repeat.key)
  474. return true;
  475. if (timerfd_settime(seat->kbd.repeat.fd, 0, &(struct itimerspec){{0}}, NULL) < 0) {
  476. LOG_ERRNO("%s: failed to disarm keyboard repeat timer", seat->name);
  477. return false;
  478. }
  479. return true;
  480. }
  481. static void
  482. keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
  483. struct wl_surface *surface)
  484. {
  485. struct seat *seat = data;
  486. LOG_DBG("keyboard_leave: keyboard=%p, serial=%u, surface=%p",
  487. (void *)wl_keyboard, serial, (void *)surface);
  488. if (seat->kbd.xkb == NULL)
  489. return;
  490. assert(
  491. seat->kbd_focus == NULL ||
  492. surface == NULL || /* Seen on Sway 1.2 */
  493. ((const struct wl_window *)wl_surface_get_user_data(surface))->term == seat->kbd_focus
  494. );
  495. struct terminal *old_focused = seat->kbd_focus;
  496. seat->kbd_focus = NULL;
  497. stop_repeater(seat, -1);
  498. seat->kbd.shift = false;
  499. seat->kbd.alt = false;
  500. seat->kbd.ctrl = false;
  501. seat->kbd.meta = false;
  502. xkb_compose_state_reset(seat->kbd.xkb_compose_state);
  503. if (old_focused != NULL) {
  504. seat->pointer.hidden = false;
  505. term_xcursor_update_for_seat(old_focused, seat);
  506. term_kbd_focus_out(old_focused);
  507. } else {
  508. /*
  509. * Sway bug - under certain conditions we get a
  510. * keyboard_leave() (and keyboard_key()) without first having
  511. * received a keyboard_enter()
  512. */
  513. LOG_WARN(
  514. "compositor sent keyboard_leave event without a keyboard_enter "
  515. "event: surface=%p", (void *)surface);
  516. }
  517. }
  518. static const struct key_data *
  519. keymap_data_for_sym(xkb_keysym_t sym, size_t *count)
  520. {
  521. switch (sym) {
  522. case XKB_KEY_Escape: *count = ALEN(key_escape); return key_escape;
  523. case XKB_KEY_Return: *count = ALEN(key_return); return key_return;
  524. case XKB_KEY_Tab: *count = ALEN(key_tab); return key_tab;
  525. case XKB_KEY_ISO_Left_Tab: *count = ALEN(key_backtab); return key_backtab;
  526. case XKB_KEY_BackSpace: *count = ALEN(key_backspace); return key_backspace;
  527. case XKB_KEY_Up: *count = ALEN(key_up); return key_up;
  528. case XKB_KEY_Down: *count = ALEN(key_down); return key_down;
  529. case XKB_KEY_Right: *count = ALEN(key_right); return key_right;
  530. case XKB_KEY_Left: *count = ALEN(key_left); return key_left;
  531. case XKB_KEY_Home: *count = ALEN(key_home); return key_home;
  532. case XKB_KEY_End: *count = ALEN(key_end); return key_end;
  533. case XKB_KEY_Insert: *count = ALEN(key_insert); return key_insert;
  534. case XKB_KEY_Delete: *count = ALEN(key_delete); return key_delete;
  535. case XKB_KEY_Page_Up: *count = ALEN(key_pageup); return key_pageup;
  536. case XKB_KEY_Page_Down: *count = ALEN(key_pagedown); return key_pagedown;
  537. case XKB_KEY_F1: *count = ALEN(key_f1); return key_f1;
  538. case XKB_KEY_F2: *count = ALEN(key_f2); return key_f2;
  539. case XKB_KEY_F3: *count = ALEN(key_f3); return key_f3;
  540. case XKB_KEY_F4: *count = ALEN(key_f4); return key_f4;
  541. case XKB_KEY_F5: *count = ALEN(key_f5); return key_f5;
  542. case XKB_KEY_F6: *count = ALEN(key_f6); return key_f6;
  543. case XKB_KEY_F7: *count = ALEN(key_f7); return key_f7;
  544. case XKB_KEY_F8: *count = ALEN(key_f8); return key_f8;
  545. case XKB_KEY_F9: *count = ALEN(key_f9); return key_f9;
  546. case XKB_KEY_F10: *count = ALEN(key_f10); return key_f10;
  547. case XKB_KEY_F11: *count = ALEN(key_f11); return key_f11;
  548. case XKB_KEY_F12: *count = ALEN(key_f12); return key_f12;
  549. case XKB_KEY_F13: *count = ALEN(key_f13); return key_f13;
  550. case XKB_KEY_F14: *count = ALEN(key_f14); return key_f14;
  551. case XKB_KEY_F15: *count = ALEN(key_f15); return key_f15;
  552. case XKB_KEY_F16: *count = ALEN(key_f16); return key_f16;
  553. case XKB_KEY_F17: *count = ALEN(key_f17); return key_f17;
  554. case XKB_KEY_F18: *count = ALEN(key_f18); return key_f18;
  555. case XKB_KEY_F19: *count = ALEN(key_f19); return key_f19;
  556. case XKB_KEY_F20: *count = ALEN(key_f20); return key_f20;
  557. case XKB_KEY_F21: *count = ALEN(key_f21); return key_f21;
  558. case XKB_KEY_F22: *count = ALEN(key_f22); return key_f22;
  559. case XKB_KEY_F23: *count = ALEN(key_f23); return key_f23;
  560. case XKB_KEY_F24: *count = ALEN(key_f24); return key_f24;
  561. case XKB_KEY_F25: *count = ALEN(key_f25); return key_f25;
  562. case XKB_KEY_F26: *count = ALEN(key_f26); return key_f26;
  563. case XKB_KEY_F27: *count = ALEN(key_f27); return key_f27;
  564. case XKB_KEY_F28: *count = ALEN(key_f28); return key_f28;
  565. case XKB_KEY_F29: *count = ALEN(key_f29); return key_f29;
  566. case XKB_KEY_F30: *count = ALEN(key_f30); return key_f30;
  567. case XKB_KEY_F31: *count = ALEN(key_f31); return key_f31;
  568. case XKB_KEY_F32: *count = ALEN(key_f32); return key_f32;
  569. case XKB_KEY_F33: *count = ALEN(key_f33); return key_f33;
  570. case XKB_KEY_F34: *count = ALEN(key_f34); return key_f34;
  571. case XKB_KEY_F35: *count = ALEN(key_f35); return key_f35;
  572. case XKB_KEY_KP_Up: *count = ALEN(key_kp_up); return key_kp_up;
  573. case XKB_KEY_KP_Down: *count = ALEN(key_kp_down); return key_kp_down;
  574. case XKB_KEY_KP_Right: *count = ALEN(key_kp_right); return key_kp_right;
  575. case XKB_KEY_KP_Left: *count = ALEN(key_kp_left); return key_kp_left;
  576. case XKB_KEY_KP_Begin: *count = ALEN(key_kp_begin); return key_kp_begin;
  577. case XKB_KEY_KP_Home: *count = ALEN(key_kp_home); return key_kp_home;
  578. case XKB_KEY_KP_End: *count = ALEN(key_kp_end); return key_kp_end;
  579. case XKB_KEY_KP_Insert: *count = ALEN(key_kp_insert); return key_kp_insert;
  580. case XKB_KEY_KP_Delete: *count = ALEN(key_kp_delete); return key_kp_delete;
  581. case XKB_KEY_KP_Page_Up: *count = ALEN(key_kp_pageup); return key_kp_pageup;
  582. case XKB_KEY_KP_Page_Down: *count = ALEN(key_kp_pagedown); return key_kp_pagedown;
  583. case XKB_KEY_KP_Enter: *count = ALEN(key_kp_enter); return key_kp_enter;
  584. case XKB_KEY_KP_Divide: *count = ALEN(key_kp_divide); return key_kp_divide;
  585. case XKB_KEY_KP_Multiply: *count = ALEN(key_kp_multiply); return key_kp_multiply;
  586. case XKB_KEY_KP_Subtract: *count = ALEN(key_kp_subtract); return key_kp_subtract;
  587. case XKB_KEY_KP_Add: *count = ALEN(key_kp_add); return key_kp_add;
  588. case XKB_KEY_KP_Separator: *count = ALEN(key_kp_separator); return key_kp_separator;
  589. case XKB_KEY_KP_Decimal: *count = ALEN(key_kp_decimal); return key_kp_decimal;
  590. case XKB_KEY_KP_0: *count = ALEN(key_kp_0); return key_kp_0;
  591. case XKB_KEY_KP_1: *count = ALEN(key_kp_1); return key_kp_1;
  592. case XKB_KEY_KP_2: *count = ALEN(key_kp_2); return key_kp_2;
  593. case XKB_KEY_KP_3: *count = ALEN(key_kp_3); return key_kp_3;
  594. case XKB_KEY_KP_4: *count = ALEN(key_kp_4); return key_kp_4;
  595. case XKB_KEY_KP_5: *count = ALEN(key_kp_5); return key_kp_5;
  596. case XKB_KEY_KP_6: *count = ALEN(key_kp_6); return key_kp_6;
  597. case XKB_KEY_KP_7: *count = ALEN(key_kp_7); return key_kp_7;
  598. case XKB_KEY_KP_8: *count = ALEN(key_kp_8); return key_kp_8;
  599. case XKB_KEY_KP_9: *count = ALEN(key_kp_9); return key_kp_9;
  600. }
  601. return NULL;
  602. }
  603. static const struct key_data *
  604. keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods)
  605. {
  606. size_t count;
  607. const struct key_data *info = keymap_data_for_sym(sym, &count);
  608. if (info == NULL)
  609. return NULL;
  610. for (size_t j = 0; j < count; j++) {
  611. if (info[j].modifiers != MOD_ANY && info[j].modifiers != mods)
  612. continue;
  613. if (info[j].cursor_keys_mode != CURSOR_KEYS_DONTCARE &&
  614. info[j].cursor_keys_mode != term->cursor_keys_mode)
  615. continue;
  616. if (info[j].keypad_keys_mode != KEYPAD_DONTCARE &&
  617. info[j].keypad_keys_mode != term->keypad_keys_mode)
  618. continue;
  619. return &info[j];
  620. }
  621. return NULL;
  622. }
  623. static void
  624. keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
  625. uint32_t time, uint32_t key, uint32_t state)
  626. {
  627. struct seat *seat = data;
  628. struct terminal *term = seat->kbd_focus;
  629. if (seat->kbd.xkb == NULL)
  630. return;
  631. assert(term != NULL);
  632. const xkb_mod_mask_t ctrl = 1 << seat->kbd.mod_ctrl;
  633. const xkb_mod_mask_t alt = 1 << seat->kbd.mod_alt;
  634. const xkb_mod_mask_t shift = 1 << seat->kbd.mod_shift;
  635. const xkb_mod_mask_t meta = 1 << seat->kbd.mod_meta;
  636. if (state == XKB_KEY_UP) {
  637. stop_repeater(seat, key);
  638. return;
  639. }
  640. key += 8;
  641. bool should_repeat = xkb_keymap_key_repeats(seat->kbd.xkb_keymap, key);
  642. xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->kbd.xkb_state, key);
  643. if (state == XKB_KEY_DOWN && term->conf->mouse.hide_when_typing &&
  644. /* TODO: better way to detect modifiers */
  645. sym != XKB_KEY_Shift_L && sym != XKB_KEY_Shift_R &&
  646. sym != XKB_KEY_Control_L && sym != XKB_KEY_Control_R &&
  647. sym != XKB_KEY_Alt_L && sym != XKB_KEY_Alt_R &&
  648. sym != XKB_KEY_ISO_Level3_Shift &&
  649. sym != XKB_KEY_Super_L && sym != XKB_KEY_Super_R &&
  650. sym != XKB_KEY_Meta_L && sym != XKB_KEY_Meta_R &&
  651. sym != XKB_KEY_Menu)
  652. {
  653. seat->pointer.hidden = true;
  654. term_xcursor_update_for_seat(term, seat);
  655. }
  656. #if 0
  657. char foo[100];
  658. xkb_keysym_get_name(sym, foo, sizeof(foo));
  659. LOG_INFO("%s", foo);
  660. #endif
  661. xkb_compose_state_feed(seat->kbd.xkb_compose_state, sym);
  662. enum xkb_compose_status compose_status = xkb_compose_state_get_status(
  663. seat->kbd.xkb_compose_state);
  664. if (compose_status == XKB_COMPOSE_COMPOSING) {
  665. /* TODO: goto maybe_repeat? */
  666. return;
  667. }
  668. xkb_mod_mask_t mods = xkb_state_serialize_mods(
  669. seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED);
  670. //xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(seat->kbd.xkb_state, key);
  671. xkb_mod_mask_t consumed = 0x0;
  672. xkb_mod_mask_t significant = ctrl | alt | shift | meta;
  673. xkb_mod_mask_t effective_mods = mods & ~consumed & significant;
  674. if (term->is_searching) {
  675. if (should_repeat)
  676. start_repeater(seat, key - 8);
  677. search_input(seat, term, key, sym, effective_mods, serial);
  678. return;
  679. }
  680. #if 0
  681. for (size_t i = 0; i < 32; i++) {
  682. if (mods & (1 << i)) {
  683. LOG_INFO("%s", xkb_keymap_mod_get_name(seat->kbd.xkb_keymap, i));
  684. }
  685. }
  686. #endif
  687. LOG_DBG("keyboard_key: keyboard=%p, serial=%u, "
  688. "sym=%u, mod=0x%08x, consumed=0x%08x, significant=0x%08x, "
  689. "effective=0x%08x, repeats=%d",
  690. (void *)wl_keyboard, serial,
  691. sym, mods, consumed, significant, effective_mods, should_repeat);
  692. /*
  693. * User configurable bindings
  694. */
  695. tll_foreach(seat->kbd.bindings.key, it) {
  696. if (it->item.bind.mods != effective_mods)
  697. continue;
  698. /* Match symbol */
  699. if (it->item.bind.sym == sym) {
  700. if (execute_binding(seat, term, it->item.action, it->item.pipe_argv, serial))
  701. goto maybe_repeat;
  702. }
  703. /* Match raw key code */
  704. tll_foreach(it->item.bind.key_codes, code) {
  705. if (code->item == key) {
  706. if (execute_binding(seat, term, it->item.action, it->item.pipe_argv, serial))
  707. goto maybe_repeat;
  708. }
  709. }
  710. }
  711. /*
  712. * Keys generating escape sequences
  713. */
  714. enum modifier keymap_mods = MOD_NONE;
  715. keymap_mods |= seat->kbd.shift ? MOD_SHIFT : MOD_NONE;
  716. keymap_mods |= seat->kbd.alt ? MOD_ALT : MOD_NONE;
  717. keymap_mods |= seat->kbd.ctrl ? MOD_CTRL : MOD_NONE;
  718. keymap_mods |= seat->kbd.meta ? MOD_META : MOD_NONE;
  719. const struct key_data *keymap = keymap_lookup(term, sym, keymap_mods);
  720. if (keymap != NULL) {
  721. term_to_slave(term, keymap->seq, strlen(keymap->seq));
  722. term_reset_view(term);
  723. selection_cancel(term);
  724. goto maybe_repeat;
  725. }
  726. /*
  727. * Compose, and maybe emit "normal" character
  728. */
  729. uint8_t buf[64] = {0};
  730. int count = 0;
  731. if (compose_status == XKB_COMPOSE_COMPOSED) {
  732. count = xkb_compose_state_get_utf8(
  733. seat->kbd.xkb_compose_state, (char *)buf, sizeof(buf));
  734. xkb_compose_state_reset(seat->kbd.xkb_compose_state);
  735. } else if (compose_status == XKB_COMPOSE_CANCELLED) {
  736. goto maybe_repeat;
  737. } else {
  738. count = xkb_state_key_get_utf8(
  739. seat->kbd.xkb_state, key, (char *)buf, sizeof(buf));
  740. }
  741. if (count == 0)
  742. goto maybe_repeat;
  743. #define is_control_key(x) ((x) >= 0x40 && (x) <= 0x7f)
  744. #define IS_CTRL(x) ((x) < 0x20 || ((x) >= 0x7f && (x) <= 0x9f))
  745. if ((keymap_mods & MOD_CTRL) &&
  746. !is_control_key(sym) &&
  747. (count == 1 && !IS_CTRL(buf[0])) &&
  748. sym < 256)
  749. {
  750. static const int mod_param_map[32] = {
  751. [MOD_SHIFT] = 2,
  752. [MOD_ALT] = 3,
  753. [MOD_SHIFT | MOD_ALT] = 4,
  754. [MOD_CTRL] = 5,
  755. [MOD_SHIFT | MOD_CTRL] = 6,
  756. [MOD_ALT | MOD_CTRL] = 7,
  757. [MOD_SHIFT | MOD_ALT | MOD_CTRL] = 8,
  758. [MOD_META] = 9,
  759. [MOD_META | MOD_SHIFT] = 10,
  760. [MOD_META | MOD_ALT] = 11,
  761. [MOD_META | MOD_SHIFT | MOD_ALT] = 12,
  762. [MOD_META | MOD_CTRL] = 13,
  763. [MOD_META | MOD_SHIFT | MOD_CTRL] = 14,
  764. [MOD_META | MOD_ALT | MOD_CTRL] = 15,
  765. [MOD_META | MOD_SHIFT | MOD_ALT | MOD_CTRL] = 16,
  766. };
  767. assert(keymap_mods < sizeof(mod_param_map) / sizeof(mod_param_map[0]));
  768. int modify_param = mod_param_map[keymap_mods];
  769. assert(modify_param != 0);
  770. char reply[1024];
  771. snprintf(reply, sizeof(reply), "\x1b[27;%d;%d~", modify_param, sym);
  772. term_to_slave(term, reply, strlen(reply));
  773. }
  774. else {
  775. if (effective_mods & alt) {
  776. /*
  777. * When the alt modifier is pressed, we do one out of three things:
  778. *
  779. * 1. we prefix the output bytes with ESC
  780. * 2. we set the 8:th bit in the output byte
  781. * 3. we ignore the alt modifier
  782. *
  783. * #1 is configured with \E[?1036, and is on by default
  784. *
  785. * If #1 has been disabled, we use #2, *if* it's a single
  786. * byte we're emitting. Since this is an UTF-8 terminal,
  787. * we then UTF8-encode the 8-bit character. #2 is
  788. * configured with \E[?1034, and is on by default.
  789. *
  790. * Lastly, if both #1 and #2 have been disabled, the alt
  791. * modifier is ignored.
  792. */
  793. if (term->meta.esc_prefix) {
  794. term_to_slave(term, "\x1b", 1);
  795. term_to_slave(term, buf, count);
  796. }
  797. else if (term->meta.eight_bit && count == 1) {
  798. const wchar_t wc = 0x80 | buf[0];
  799. char utf8[8];
  800. mbstate_t ps = {0};
  801. size_t chars = wcrtomb(utf8, wc, &ps);
  802. if (chars != (size_t)-1)
  803. term_to_slave(term, utf8, chars);
  804. else
  805. term_to_slave(term, buf, count);
  806. }
  807. else {
  808. /* Alt ignored */
  809. term_to_slave(term, buf, count);
  810. }
  811. } else
  812. term_to_slave(term, buf, count);
  813. }
  814. term_reset_view(term);
  815. selection_cancel(term);
  816. maybe_repeat:
  817. clock_gettime(
  818. term->wl->presentation_clock_id, &term->render.input_time);
  819. if (should_repeat)
  820. start_repeater(seat, key - 8);
  821. }
  822. static void
  823. keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
  824. uint32_t mods_depressed, uint32_t mods_latched,
  825. uint32_t mods_locked, uint32_t group)
  826. {
  827. struct seat *seat = data;
  828. LOG_DBG("modifiers: depressed=0x%x, latched=0x%x, locked=0x%x, group=%u",
  829. mods_depressed, mods_latched, mods_locked, group);
  830. if (seat->kbd.xkb == NULL)
  831. return;
  832. xkb_state_update_mask(
  833. seat->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
  834. /* Update state of modifiers we're interested in for e.g mouse events */
  835. seat->kbd.shift = xkb_state_mod_index_is_active(
  836. seat->kbd.xkb_state, seat->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED);
  837. seat->kbd.alt = xkb_state_mod_index_is_active(
  838. seat->kbd.xkb_state, seat->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED);
  839. seat->kbd.ctrl = xkb_state_mod_index_is_active(
  840. seat->kbd.xkb_state, seat->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED);
  841. seat->kbd.meta = xkb_state_mod_index_is_active(
  842. seat->kbd.xkb_state, seat->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED);
  843. if (seat->kbd_focus && seat->kbd_focus->active_surface == TERM_SURF_GRID)
  844. term_xcursor_update_for_seat(seat->kbd_focus, seat);
  845. }
  846. static void
  847. keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
  848. int32_t rate, int32_t delay)
  849. {
  850. struct seat *seat = data;
  851. LOG_DBG("keyboard repeat: rate=%d, delay=%d", rate, delay);
  852. seat->kbd.repeat.rate = rate;
  853. seat->kbd.repeat.delay = delay;
  854. }
  855. const struct wl_keyboard_listener keyboard_listener = {
  856. .keymap = &keyboard_keymap,
  857. .enter = &keyboard_enter,
  858. .leave = &keyboard_leave,
  859. .key = &keyboard_key,
  860. .modifiers = &keyboard_modifiers,
  861. .repeat_info = &keyboard_repeat_info,
  862. };
  863. void
  864. input_repeat(struct seat *seat, uint32_t key)
  865. {
  866. keyboard_key(seat, NULL, seat->kbd.serial, 0, key, XKB_KEY_DOWN);
  867. }
  868. static bool
  869. is_top_left(const struct terminal *term, int x, int y)
  870. {
  871. int csd_border_size = term->conf->csd.border_width;
  872. return (
  873. (term->active_surface == TERM_SURF_BORDER_LEFT && y < 10 * term->scale) ||
  874. (term->active_surface == TERM_SURF_BORDER_TOP && x < (10 + csd_border_size) * term->scale));
  875. }
  876. static bool
  877. is_top_right(const struct terminal *term, int x, int y)
  878. {
  879. int csd_border_size = term->conf->csd.border_width;
  880. return (
  881. (term->active_surface == TERM_SURF_BORDER_RIGHT && y < 10 * term->scale) ||
  882. (term->active_surface == TERM_SURF_BORDER_TOP && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale));
  883. }
  884. static bool
  885. is_bottom_left(const struct terminal *term, int x, int y)
  886. {
  887. int csd_title_size = term->conf->csd.title_height;
  888. int csd_border_size = term->conf->csd.border_width;
  889. return (
  890. (term->active_surface == TERM_SURF_BORDER_LEFT && y > csd_title_size * term->scale + term->height) ||
  891. (term->active_surface == TERM_SURF_BORDER_BOTTOM && x < (10 + csd_border_size) * term->scale));
  892. }
  893. static bool
  894. is_bottom_right(const struct terminal *term, int x, int y)
  895. {
  896. int csd_title_size = term->conf->csd.title_height;
  897. int csd_border_size = term->conf->csd.border_width;
  898. return (
  899. (term->active_surface == TERM_SURF_BORDER_RIGHT && y > csd_title_size * term->scale + term->height) ||
  900. (term->active_surface == TERM_SURF_BORDER_BOTTOM && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale));
  901. }
  902. static const char *
  903. xcursor_for_csd_border(struct terminal *term, int x, int y)
  904. {
  905. if (is_top_left(term, x, y)) return XCURSOR_TOP_LEFT_CORNER;
  906. else if (is_top_right(term, x, y)) return XCURSOR_TOP_RIGHT_CORNER;
  907. else if (is_bottom_left(term, x, y)) return XCURSOR_BOTTOM_LEFT_CORNER;
  908. else if (is_bottom_right(term, x, y)) return XCURSOR_BOTTOM_RIGHT_CORNER;
  909. else if (term->active_surface == TERM_SURF_BORDER_LEFT) return XCURSOR_LEFT_SIDE;
  910. else if (term->active_surface == TERM_SURF_BORDER_RIGHT) return XCURSOR_RIGHT_SIDE;
  911. else if (term->active_surface == TERM_SURF_BORDER_TOP) return XCURSOR_TOP_SIDE;
  912. else if (term->active_surface == TERM_SURF_BORDER_BOTTOM) return XCURSOR_BOTTOM_SIDE;
  913. else {
  914. assert(false);
  915. return NULL;
  916. }
  917. }
  918. static void
  919. wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
  920. uint32_t serial, struct wl_surface *surface,
  921. wl_fixed_t surface_x, wl_fixed_t surface_y)
  922. {
  923. assert(surface != NULL);
  924. struct seat *seat = data;
  925. struct wl_window *win = wl_surface_get_user_data(surface);
  926. struct terminal *term = win->term;
  927. seat->pointer.serial = serial;
  928. seat->pointer.hidden = false;
  929. LOG_DBG("pointer-enter: pointer=%p, serial=%u, surface = %p, new-moused = %p",
  930. (void *)wl_pointer, serial, (void *)surface, (void *)term);
  931. /* Scale may have changed */
  932. wayl_reload_xcursor_theme(seat, term->scale);
  933. seat->mouse_focus = term;
  934. int x = wl_fixed_to_int(surface_x) * term->scale;
  935. int y = wl_fixed_to_int(surface_y) * term->scale;
  936. switch ((term->active_surface = term_surface_kind(term, surface))) {
  937. case TERM_SURF_GRID: {
  938. /*
  939. * Translate x,y pixel coordinate to a cell coordinate, or -1
  940. * if the cursor is outside the grid. I.e. if it is inside the
  941. * margins.
  942. */
  943. if (x < term->margins.left || x >= term->width - term->margins.right)
  944. seat->mouse.col = -1;
  945. else
  946. seat->mouse.col = (x - term->margins.left) / term->cell_width;
  947. if (y < term->margins.top || y >= term->height - term->margins.bottom)
  948. seat->mouse.row = -1;
  949. else
  950. seat->mouse.row = (y - term->margins.top) / term->cell_height;
  951. term_xcursor_update_for_seat(term, seat);
  952. break;
  953. }
  954. case TERM_SURF_SEARCH:
  955. case TERM_SURF_SCROLLBACK_INDICATOR:
  956. case TERM_SURF_RENDER_TIMER:
  957. case TERM_SURF_TITLE:
  958. render_xcursor_set(seat, term, XCURSOR_LEFT_PTR);
  959. break;
  960. case TERM_SURF_BORDER_LEFT:
  961. case TERM_SURF_BORDER_RIGHT:
  962. case TERM_SURF_BORDER_TOP:
  963. case TERM_SURF_BORDER_BOTTOM:
  964. render_xcursor_set(seat, term, xcursor_for_csd_border(term, x, y));
  965. break;
  966. case TERM_SURF_BUTTON_MINIMIZE:
  967. case TERM_SURF_BUTTON_MAXIMIZE:
  968. case TERM_SURF_BUTTON_CLOSE:
  969. render_xcursor_set(seat, term, XCURSOR_LEFT_PTR);
  970. render_refresh_csd(term);
  971. break;
  972. case TERM_SURF_NONE:
  973. assert(false);
  974. break;
  975. }
  976. }
  977. static void
  978. wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
  979. uint32_t serial, struct wl_surface *surface)
  980. {
  981. struct seat *seat = data;
  982. struct terminal *old_moused = seat->mouse_focus;
  983. LOG_DBG(
  984. "%s: pointer-leave: pointer=%p, serial=%u, surface = %p, old-moused = %p",
  985. seat->name, (void *)wl_pointer, serial, (void *)surface,
  986. (void *)old_moused);
  987. seat->pointer.hidden = false;
  988. if (seat->pointer.xcursor_callback != NULL) {
  989. /* A cursor frame callback may never be called if the pointer leaves our surface */
  990. wl_callback_destroy(seat->pointer.xcursor_callback);
  991. seat->pointer.xcursor_callback = NULL;
  992. seat->pointer.xcursor_pending = false;
  993. seat->pointer.xcursor = NULL;
  994. }
  995. /* Reset mouse state */
  996. seat->mouse.x = seat->mouse.y = 0;
  997. seat->mouse.col = seat->mouse.row = 0;
  998. seat->mouse.button = seat->mouse.last_button = seat->mouse.count = 0;
  999. seat->mouse.consumed = false;
  1000. memset(&seat->mouse.last_time, 0, sizeof(seat->mouse.last_time));
  1001. seat->mouse.axis_aggregated = 0.0;
  1002. seat->mouse.have_discrete = false;
  1003. seat->mouse_focus = NULL;
  1004. if (old_moused == NULL) {
  1005. LOG_WARN(
  1006. "compositor sent pointer_leave event without a pointer_enter "
  1007. "event: surface=%p", (void *)surface);
  1008. } else {
  1009. if (surface != NULL) {
  1010. /* Sway 1.4 sends this event with a NULL surface when we destroy the window */
  1011. const struct wl_window UNUSED *win = wl_surface_get_user_data(surface);
  1012. assert(old_moused == win->term);
  1013. }
  1014. enum term_surface active_surface = old_moused->active_surface;
  1015. old_moused->active_surface = TERM_SURF_NONE;
  1016. term_xcursor_update_for_seat(old_moused, seat);
  1017. switch (active_surface) {
  1018. case TERM_SURF_BUTTON_MINIMIZE:
  1019. case TERM_SURF_BUTTON_MAXIMIZE:
  1020. case TERM_SURF_BUTTON_CLOSE:
  1021. if (old_moused->is_shutting_down)
  1022. break;
  1023. render_refresh_csd(old_moused);
  1024. break;
  1025. case TERM_SURF_NONE:
  1026. case TERM_SURF_GRID:
  1027. case TERM_SURF_SEARCH:
  1028. case TERM_SURF_SCROLLBACK_INDICATOR:
  1029. case TERM_SURF_RENDER_TIMER:
  1030. case TERM_SURF_TITLE:
  1031. case TERM_SURF_BORDER_LEFT:
  1032. case TERM_SURF_BORDER_RIGHT:
  1033. case TERM_SURF_BORDER_TOP:
  1034. case TERM_SURF_BORDER_BOTTOM:
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. static void
  1040. wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
  1041. uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
  1042. {
  1043. struct seat *seat = data;
  1044. struct wayland *wayl = seat->wayl;
  1045. struct terminal *term = seat->mouse_focus;
  1046. struct wl_window *win = term->window;
  1047. LOG_DBG("pointer_motion: pointer=%p, x=%d, y=%d", (void *)wl_pointer,
  1048. wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y));
  1049. assert(term != NULL);
  1050. int x = wl_fixed_to_int(surface_x) * term->scale;
  1051. int y = wl_fixed_to_int(surface_y) * term->scale;
  1052. seat->pointer.hidden = false;
  1053. seat->mouse.x = x;
  1054. seat->mouse.y = y;
  1055. switch (term->active_surface) {
  1056. case TERM_SURF_NONE:
  1057. case TERM_SURF_SEARCH:
  1058. case TERM_SURF_SCROLLBACK_INDICATOR:
  1059. case TERM_SURF_RENDER_TIMER:
  1060. case TERM_SURF_BUTTON_MINIMIZE:
  1061. case TERM_SURF_BUTTON_MAXIMIZE:
  1062. case TERM_SURF_BUTTON_CLOSE:
  1063. break;
  1064. case TERM_SURF_TITLE:
  1065. /* We've started a 'move' timer, but user started dragging
  1066. * right away - abort the timer and initiate the actual move
  1067. * right away */
  1068. if (seat->mouse.button == BTN_LEFT && win->csd.move_timeout_fd != -1) {
  1069. fdm_del(wayl->fdm, win->csd.move_timeout_fd);
  1070. win->csd.move_timeout_fd = -1;
  1071. xdg_toplevel_move(win->xdg_toplevel, seat->wl_seat, win->csd.serial);
  1072. }
  1073. break;
  1074. case TERM_SURF_BORDER_LEFT:
  1075. case TERM_SURF_BORDER_RIGHT:
  1076. case TERM_SURF_BORDER_TOP:
  1077. case TERM_SURF_BORDER_BOTTOM:
  1078. render_xcursor_set(seat, term, xcursor_for_csd_border(term, x, y));
  1079. break;
  1080. case TERM_SURF_GRID: {
  1081. int old_col = seat->mouse.col;
  1082. int old_row = seat->mouse.row;
  1083. /*
  1084. * While the seat's mouse coordinates must always be on the
  1085. * grid, or -1, we allow updating the selection even when the
  1086. * mouse is outside the grid (could also be outside the
  1087. * terminal window).
  1088. */
  1089. int selection_col;
  1090. int selection_row;
  1091. if (x < term->margins.left) {
  1092. seat->mouse.col = -1;
  1093. selection_col = 0;
  1094. } else if (x >= term->width - term->margins.right) {
  1095. seat->mouse.col = -1;
  1096. selection_col = term->cols - 1;
  1097. } else {
  1098. seat->mouse.col = (x - term->margins.left) / term->cell_width;
  1099. selection_col = seat->mouse.col;
  1100. }
  1101. if (y < term->margins.top) {
  1102. seat->mouse.row = -1;
  1103. selection_row = 0;
  1104. } else if (y >= term->height - term->margins.bottom) {
  1105. seat->mouse.row = -1;
  1106. selection_row = term->rows - 1;
  1107. } else {
  1108. seat->mouse.row = (y - term->margins.top) / term->cell_height;
  1109. selection_row = seat->mouse.row;
  1110. }
  1111. assert(seat->mouse.col == -1 || (seat->mouse.col >= 0 && seat->mouse.col < term->cols));
  1112. assert(seat->mouse.row == -1 || (seat->mouse.row >= 0 && seat->mouse.row < term->rows));
  1113. term_xcursor_update_for_seat(term, seat);
  1114. /* Cursor has moved to a different cell since last time */
  1115. bool cursor_is_on_new_cell
  1116. = old_col != seat->mouse.col || old_row != seat->mouse.row;
  1117. /* Cursor is inside the grid, i.e. *not* in the margins */
  1118. const bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
  1119. enum selection_scroll_direction auto_scroll_direction
  1120. = y < term->margins.top ? SELECTION_SCROLL_UP
  1121. : y > term->height - term->margins.bottom ? SELECTION_SCROLL_DOWN
  1122. : SELECTION_SCROLL_NOT;
  1123. if (auto_scroll_direction == SELECTION_SCROLL_NOT)
  1124. selection_stop_scroll_timer(term);
  1125. /* Update selection */
  1126. if (!term->is_searching) {
  1127. if (auto_scroll_direction != SELECTION_SCROLL_NOT) {
  1128. /*
  1129. * Start ‘selection auto-scrolling’
  1130. *
  1131. * The speed of the scrolling is proportional to the
  1132. * distance between the mouse and the grid; the
  1133. * further away the mouse is, the faster we scroll.
  1134. *
  1135. * Note that the speed is measured in ‘intervals (in
  1136. * ns) between each timed scroll of a single line’.
  1137. *
  1138. * Thus, the further away the mouse is, the smaller
  1139. * interval value we use.
  1140. */
  1141. int distance = auto_scroll_direction == SELECTION_SCROLL_UP
  1142. ? term->margins.top - y
  1143. : y - (term->height - term->margins.bottom);
  1144. assert(distance > 0);
  1145. int divisor
  1146. = distance * term->conf->scrollback.multiplier / term->scale;
  1147. selection_start_scroll_timer(
  1148. term, 400000000 / (divisor > 0 ? divisor : 1),
  1149. auto_scroll_direction, selection_col);
  1150. }
  1151. if (cursor_is_on_new_cell || term->selection.end.row < 0)
  1152. selection_update(term, selection_col, selection_row);
  1153. }
  1154. /* Send mouse event to client application */
  1155. if (!seat->mouse.consumed &&
  1156. !term_mouse_grabbed(term, seat) &&
  1157. cursor_is_on_new_cell && cursor_is_on_grid)
  1158. {
  1159. assert(seat->mouse.col < term->cols);
  1160. assert(seat->mouse.row < term->rows);
  1161. term_mouse_motion(
  1162. term, seat->mouse.button, seat->mouse.row, seat->mouse.col,
  1163. seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
  1164. }
  1165. break;
  1166. }
  1167. }
  1168. }
  1169. static bool
  1170. fdm_csd_move(struct fdm *fdm, int fd, int events, void *data)
  1171. {
  1172. struct seat *seat = data;
  1173. fdm_del(fdm, fd);
  1174. if (seat->mouse_focus == NULL) {
  1175. LOG_WARN(
  1176. "%s: CSD move timeout triggered, but seat's has no mouse focused terminal",
  1177. seat->name);
  1178. return true;
  1179. }
  1180. struct wl_window *win = seat->mouse_focus->window;
  1181. win->csd.move_timeout_fd = -1;
  1182. xdg_toplevel_move(win->xdg_toplevel, seat->wl_seat, win->csd.serial);
  1183. return true;
  1184. }
  1185. static void
  1186. wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
  1187. uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
  1188. {
  1189. LOG_DBG("BUTTON: pointer=%p, serial=%u, button=%x, state=%u",
  1190. (void *)wl_pointer, serial, button, state);
  1191. struct seat *seat = data;
  1192. struct wayland *wayl = seat->wayl;
  1193. struct terminal *term = seat->mouse_focus;
  1194. seat->pointer.hidden = false;
  1195. assert(term != NULL);
  1196. /* Update double/triple click state */
  1197. if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
  1198. /* Time since last click */
  1199. struct timeval now, since_last;
  1200. gettimeofday(&now, NULL);
  1201. timersub(&now, &seat->mouse.last_time, &since_last);
  1202. /* Double- or triple click? */
  1203. if (button == seat->mouse.last_button &&
  1204. since_last.tv_sec == 0 &&
  1205. since_last.tv_usec <= 300 * 1000)
  1206. {
  1207. seat->mouse.count++;
  1208. } else
  1209. seat->mouse.count = 1;
  1210. seat->mouse.button = button; /* For motion events */
  1211. seat->mouse.last_button = button;
  1212. seat->mouse.last_time = now;
  1213. } else
  1214. seat->mouse.button = 0; /* For motion events */
  1215. switch (term->active_surface) {
  1216. case TERM_SURF_TITLE:
  1217. if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
  1218. struct wl_window *win = term->window;
  1219. /* Toggle maximized state on double-click */
  1220. if (button == BTN_LEFT && seat->mouse.count == 2) {
  1221. if (win->is_maximized)
  1222. xdg_toplevel_unset_maximized(win->xdg_toplevel);
  1223. else
  1224. xdg_toplevel_set_maximized(win->xdg_toplevel);
  1225. }
  1226. else if (button == BTN_LEFT && win->csd.move_timeout_fd == -1) {
  1227. const struct itimerspec timeout = {
  1228. .it_value = {.tv_nsec = 200000000},
  1229. };
  1230. int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
  1231. if (fd >= 0 &&
  1232. timerfd_settime(fd, 0, &timeout, NULL) == 0 &&
  1233. fdm_add(wayl->fdm, fd, EPOLLIN, &fdm_csd_move, seat))
  1234. {
  1235. win->csd.move_timeout_fd = fd;
  1236. win->csd.serial = serial;
  1237. } else {
  1238. LOG_ERRNO("failed to configure XDG toplevel move timer FD");
  1239. close(fd);
  1240. }
  1241. }
  1242. }
  1243. else if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
  1244. struct wl_window *win = term->window;
  1245. if (win->csd.move_timeout_fd != -1) {
  1246. fdm_del(wayl->fdm, win->csd.move_timeout_fd);
  1247. win->csd.move_timeout_fd = -1;
  1248. }
  1249. }
  1250. return;
  1251. case TERM_SURF_BORDER_LEFT:
  1252. case TERM_SURF_BORDER_RIGHT:
  1253. case TERM_SURF_BORDER_TOP:
  1254. case TERM_SURF_BORDER_BOTTOM: {
  1255. static const enum xdg_toplevel_resize_edge map[] = {
  1256. [TERM_SURF_BORDER_LEFT] = XDG_TOPLEVEL_RESIZE_EDGE_LEFT,
  1257. [TERM_SURF_BORDER_RIGHT] = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
  1258. [TERM_SURF_BORDER_TOP] = XDG_TOPLEVEL_RESIZE_EDGE_TOP,
  1259. [TERM_SURF_BORDER_BOTTOM] = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM,
  1260. };
  1261. if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
  1262. enum xdg_toplevel_resize_edge resize_type;
  1263. int x = seat->mouse.x;
  1264. int y = seat->mouse.y;
  1265. if (is_top_left(term, x, y))
  1266. resize_type = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
  1267. else if (is_top_right(term, x, y))
  1268. resize_type = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
  1269. else if (is_bottom_left(term, x, y))
  1270. resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
  1271. else if (is_bottom_right(term, x, y))
  1272. resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
  1273. else
  1274. resize_type = map[term->active_surface];
  1275. xdg_toplevel_resize(
  1276. term->window->xdg_toplevel, seat->wl_seat, serial, resize_type);
  1277. }
  1278. return;
  1279. }
  1280. case TERM_SURF_BUTTON_MINIMIZE:
  1281. if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
  1282. xdg_toplevel_set_minimized(term->window->xdg_toplevel);
  1283. break;
  1284. case TERM_SURF_BUTTON_MAXIMIZE:
  1285. if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
  1286. if (term->window->is_maximized)
  1287. xdg_toplevel_unset_maximized(term->window->xdg_toplevel);
  1288. else
  1289. xdg_toplevel_set_maximized(term->window->xdg_toplevel);
  1290. }
  1291. break;
  1292. case TERM_SURF_BUTTON_CLOSE:
  1293. if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
  1294. term_shutdown(term);
  1295. break;
  1296. case TERM_SURF_SEARCH:
  1297. case TERM_SURF_SCROLLBACK_INDICATOR:
  1298. case TERM_SURF_RENDER_TIMER:
  1299. break;
  1300. case TERM_SURF_GRID: {
  1301. search_cancel(term);
  1302. bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
  1303. switch (state) {
  1304. case WL_POINTER_BUTTON_STATE_PRESSED: {
  1305. if (!seat->mouse.consumed) {
  1306. if (seat->wl_keyboard != NULL) {
  1307. /* Seat has keyboard - use mouse bindings *with* modifiers */
  1308. xkb_mod_mask_t mods = xkb_state_serialize_mods(
  1309. seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED);
  1310. /* Ignore Shift when matching modifiers, since it is
  1311. * used to enable selection in mouse grabbing client
  1312. * applications */
  1313. mods &= ~(1 << seat->kbd.mod_shift);
  1314. const struct mouse_binding *match = NULL;
  1315. tll_foreach(seat->mouse.bindings, it) {
  1316. const struct mouse_binding *binding = &it->item;
  1317. if (binding->button != button) {
  1318. /* Wrong button */
  1319. continue;
  1320. }
  1321. if (binding->mods != mods) {
  1322. /* Modifier mismatch */
  1323. continue;
  1324. }
  1325. if (binding->count > seat->mouse.count) {
  1326. /* Not correct click count */
  1327. continue;
  1328. }
  1329. if (match == NULL || binding->count > match->count)
  1330. match = binding;
  1331. }
  1332. if (match != NULL) {
  1333. seat->mouse.consumed = execute_binding(
  1334. seat, term, match->action, NULL, serial);
  1335. }
  1336. }
  1337. else {
  1338. /* Seat does NOT have a keyboard - use mouse bindings *without* modifiers */
  1339. const struct config_mouse_binding *match = NULL;
  1340. tll_foreach(seat->wayl->conf->bindings.mouse, it) {
  1341. const struct config_mouse_binding *binding = &it->item;
  1342. if (binding->button != button) {
  1343. /* Wrong button */
  1344. continue;
  1345. }
  1346. if (binding->count > seat->mouse.count) {
  1347. /* Incorrect click count */
  1348. continue;
  1349. }
  1350. const struct config_key_modifiers no_mods = {0};
  1351. if (memcmp(&binding->modifiers, &no_mods, sizeof(no_mods)) != 0) {
  1352. /* Binding has modifiers */
  1353. continue;
  1354. }
  1355. if (match == NULL || binding->count > match->count)
  1356. match = binding;
  1357. }
  1358. if (match != NULL) {
  1359. seat->mouse.consumed = execute_binding(
  1360. seat, term, match->action, NULL, serial);
  1361. }
  1362. }
  1363. }
  1364. if (!seat->mouse.consumed &&
  1365. !term_mouse_grabbed(term, seat) &&
  1366. cursor_is_on_grid)
  1367. {
  1368. term_mouse_down(
  1369. term, button, seat->mouse.row, seat->mouse.col,
  1370. seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
  1371. }
  1372. break;
  1373. }
  1374. case WL_POINTER_BUTTON_STATE_RELEASED:
  1375. selection_finalize(seat, term, serial);
  1376. if (!seat->mouse.consumed &&
  1377. !term_mouse_grabbed(term, seat) &&
  1378. cursor_is_on_grid)
  1379. {
  1380. term_mouse_up(
  1381. term, button, seat->mouse.row, seat->mouse.col,
  1382. seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
  1383. }
  1384. seat->mouse.consumed = false;
  1385. break;
  1386. }
  1387. break;
  1388. }
  1389. case TERM_SURF_NONE:
  1390. assert(false);
  1391. break;
  1392. }
  1393. }
  1394. static void
  1395. alternate_scroll(struct seat *seat, int amount, int button)
  1396. {
  1397. if (seat->wl_keyboard == NULL)
  1398. return;
  1399. xkb_keycode_t key = button == BTN_BACK
  1400. ? seat->kbd.key_arrow_up : seat->kbd.key_arrow_down;
  1401. for (int i = 0; i < amount; i++)
  1402. keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN);
  1403. keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_UP);
  1404. }
  1405. static void
  1406. mouse_scroll(struct seat *seat, int amount)
  1407. {
  1408. struct terminal *term = seat->mouse_focus;
  1409. assert(term != NULL);
  1410. int button = amount < 0 ? BTN_BACK : BTN_FORWARD;
  1411. amount = abs(amount);
  1412. if (term->mouse_tracking == MOUSE_NONE) {
  1413. if (term->grid == &term->alt) {
  1414. if (term->alt_scrolling)
  1415. alternate_scroll(seat, amount, button);
  1416. } else {
  1417. if (button == BTN_BACK)
  1418. cmd_scrollback_up(term, amount);
  1419. else
  1420. cmd_scrollback_down(term, amount);
  1421. }
  1422. } else if (!term_mouse_grabbed(term, seat) &&
  1423. seat->mouse.col >= 0 && seat->mouse.row >= 0)
  1424. {
  1425. assert(seat->mouse.col < term->cols);
  1426. assert(seat->mouse.row < term->rows);
  1427. for (int i = 0; i < amount; i++) {
  1428. term_mouse_down(
  1429. term, button, seat->mouse.row, seat->mouse.col,
  1430. seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
  1431. }
  1432. term_mouse_up(
  1433. term, button, seat->mouse.row, seat->mouse.col,
  1434. seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
  1435. }
  1436. }
  1437. static void
  1438. wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
  1439. uint32_t time, uint32_t axis, wl_fixed_t value)
  1440. {
  1441. if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
  1442. return;
  1443. struct seat *seat = data;
  1444. if (seat->mouse.have_discrete)
  1445. return;
  1446. assert(seat->mouse_focus != NULL);
  1447. /*
  1448. * Aggregate scrolled amount until we get at least 1.0
  1449. *
  1450. * Without this, very slow scrolling will never actually scroll
  1451. * anything.
  1452. */
  1453. seat->mouse.axis_aggregated
  1454. += seat->wayl->conf->scrollback.multiplier * wl_fixed_to_double(value);
  1455. if (fabs(seat->mouse.axis_aggregated) < seat->mouse_focus->cell_height)
  1456. return;
  1457. int lines = seat->mouse.axis_aggregated / seat->mouse_focus->cell_height;
  1458. mouse_scroll(seat, lines);
  1459. seat->mouse.axis_aggregated -= (double)lines * seat->mouse_focus->cell_height;
  1460. }
  1461. static void
  1462. wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
  1463. uint32_t axis, int32_t discrete)
  1464. {
  1465. if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
  1466. return;
  1467. struct seat *seat = data;
  1468. seat->mouse.have_discrete = true;
  1469. mouse_scroll(seat, seat->wayl->conf->scrollback.multiplier * discrete);
  1470. }
  1471. static void
  1472. wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
  1473. {
  1474. struct seat *seat = data;
  1475. seat->mouse.have_discrete = false;
  1476. }
  1477. static void
  1478. wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer,
  1479. uint32_t axis_source)
  1480. {
  1481. }
  1482. static void
  1483. wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
  1484. uint32_t time, uint32_t axis)
  1485. {
  1486. if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
  1487. return;
  1488. struct seat *seat = data;
  1489. seat->mouse.axis_aggregated = 0.;
  1490. }
  1491. const struct wl_pointer_listener pointer_listener = {
  1492. .enter = wl_pointer_enter,
  1493. .leave = wl_pointer_leave,
  1494. .motion = wl_pointer_motion,
  1495. .button = wl_pointer_button,
  1496. .axis = wl_pointer_axis,
  1497. .frame = wl_pointer_frame,
  1498. .axis_source = wl_pointer_axis_source,
  1499. .axis_stop = wl_pointer_axis_stop,
  1500. .axis_discrete = wl_pointer_axis_discrete,
  1501. };