From 4ecb0ecf4d1f45df918a8dd2dbabd6e9d7090dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 15:58:52 +0100 Subject: [PATCH 01/19] wayland: rename focused/moused to kbd_focus/mouse_focus --- input.c | 34 +++++++++++++++++----------------- render.c | 2 +- terminal.c | 24 ++++++++++++------------ wayland.c | 4 ++-- wayland.h | 4 ++-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/input.c b/input.c index fd15b392..ebbcac74 100644 --- a/input.c +++ b/input.c @@ -87,11 +87,11 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wayland *wayl = data; wayl->input_serial = serial; - wayl->focused = wayl_terminal_from_surface(wayl, surface); - assert(wayl->focused != NULL); + wayl->kbd_focus = wayl_terminal_from_surface(wayl, surface); + assert(wayl->kbd_focus != NULL); - term_focus_in(wayl->focused); - term_xcursor_update(wayl->focused); + term_focus_in(wayl->kbd_focus); + term_xcursor_update(wayl->kbd_focus); } static bool @@ -143,12 +143,12 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wayland *wayl = data; assert( - wayl->focused == NULL || + wayl->kbd_focus == NULL || surface == NULL || /* Seen on Sway 1.2 */ - wayl_terminal_from_surface(wayl, surface) == wayl->focused); + wayl_terminal_from_surface(wayl, surface) == wayl->kbd_focus); - struct terminal *old_focused = wayl->focused; - wayl->focused = NULL; + struct terminal *old_focused = wayl->kbd_focus; + wayl->kbd_focus = NULL; stop_repeater(wayl, -1); if (old_focused != NULL) { @@ -171,7 +171,7 @@ 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->focused; + struct terminal *term = wayl->kbd_focus; /* Workaround buggy Sway 1.2 */ if (term == NULL) { @@ -409,8 +409,8 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, wayl->kbd.meta = xkb_state_mod_index_is_active( wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); - if (wayl->focused) - term_xcursor_update(wayl->focused); + if (wayl->kbd_focus) + term_xcursor_update(wayl->kbd_focus); } static void @@ -450,7 +450,7 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, LOG_DBG("pointer-enter: surface = %p, new-moused = %p", surface, term); - wayl->moused = term; + wayl->mouse_focus = term; int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; @@ -466,11 +466,11 @@ 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->moused; + struct terminal *old_moused = wayl->mouse_focus; LOG_DBG("pointer-leave: surface = %p, old-moused = %p", surface, old_moused); - wayl->moused = NULL; + wayl->mouse_focus = NULL; if (old_moused == NULL) { LOG_WARN( "compositor sent pointer_leave event without a pointer_enter " @@ -484,7 +484,7 @@ 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->moused; + struct terminal *term = wayl->mouse_focus; /* Workaround buggy Sway 1.2 */ if (term == NULL) { @@ -540,7 +540,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, LOG_DBG("BUTTON: button=%x, state=%u", button, state); struct wayland *wayl = data; - struct terminal *term = wayl->moused; + struct terminal *term = wayl->mouse_focus; /* Workaround buggy Sway 1.2 */ if (term == NULL) { @@ -621,7 +621,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, static void mouse_scroll(struct wayland *wayl, int amount) { - struct terminal *term = wayl->moused; + struct terminal *term = wayl->mouse_focus; assert(term != NULL); int button = amount < 0 ? BTN_BACK : BTN_FORWARD; diff --git a/render.c b/render.c index 97284cbb..d02ada3e 100644 --- a/render.c +++ b/render.c @@ -279,7 +279,7 @@ draw_cursor(const struct terminal *term, const struct cell *cell, pixman_image_t *pix, pixman_color_t *fg, const pixman_color_t *bg, int x, int y, int cols) { - bool have_focus = term->wl->focused == term; + bool have_focus = term->wl->kbd_focus == term; pixman_color_t cursor_color; pixman_color_t text_color; diff --git a/terminal.c b/terminal.c index 64bdebe3..a9ed686f 100644 --- a/terminal.c +++ b/terminal.c @@ -716,13 +716,13 @@ 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->focused == term) - wayl->focused = NULL; - if (wayl->moused == term) - wayl->moused = NULL; + if (wayl->kbd_focus == term) + wayl->kbd_focus = NULL; + if (wayl->mouse_focus == term) + wayl->mouse_focus = NULL; - assert(wayl->focused != term); - assert(wayl->moused != term); + assert(wayl->kbd_focus != term); + assert(wayl->mouse_focus != term); void (*cb)(void *, int) = term->shutdown_cb; void *cb_data = term->shutdown_data; @@ -1234,7 +1234,7 @@ void term_cursor_blink_enable(struct terminal *term) { term->cursor_blink.state = CURSOR_BLINK_ON; - term->cursor_blink.active = term->wl->focused == term + term->cursor_blink.active = term->wl->kbd_focus == term ? cursor_blink_start_timer(term) : true; cursor_refresh(term); } @@ -1253,7 +1253,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->focused == term + term->cursor_blink.active = term->wl->kbd_focus == term ? cursor_blink_start_timer(term) : true; } } @@ -1508,7 +1508,7 @@ term_mouse_grabbed(const struct terminal *term) * Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not. */ return - term->wl->focused == term && + term->wl->kbd_focus == term && term->wl->kbd.shift && !term->wl->kbd.alt && !term->wl->kbd.ctrl && !term->wl->kbd.meta; } @@ -1529,7 +1529,7 @@ term_mouse_down(struct terminal *term, int button, int row, int col) return; - bool has_focus = term->wl->focused == term; + 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; @@ -1573,7 +1573,7 @@ term_mouse_up(struct terminal *term, int button, int row, int col) if (encoded == -1) return; - bool has_focus = term->wl->focused == term; + 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; @@ -1617,7 +1617,7 @@ term_mouse_motion(struct terminal *term, int button, int row, int col) } else encoded = 3; /* "released" */ - bool has_focus = term->wl->focused == term; + 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; diff --git a/wayland.c b/wayland.c index cbd49179..380cc526 100644 --- a/wayland.c +++ b/wayland.c @@ -849,12 +849,12 @@ wayl_cursor_set(struct wayland *wayl, const struct terminal *term) if (wayl->pointer.theme == NULL) return false; - if (wayl->moused == NULL) { + if (wayl->mouse_focus == NULL) { wayl->pointer.xcursor = NULL; return true; } - if (wayl->moused != term) { + if (wayl->mouse_focus != term) { /* This terminal doesn't have mouse focus */ return true; } diff --git a/wayland.h b/wayland.h index d10f10e3..dfdcfffd 100644 --- a/wayland.h +++ b/wayland.h @@ -164,8 +164,8 @@ struct wayland { tll(struct monitor) monitors; /* All available outputs */ tll(struct terminal *) terms; - struct terminal *focused; - struct terminal *moused; + struct terminal *kbd_focus; + struct terminal *mouse_focus; }; struct wayland *wayl_init(const struct config *conf, struct fdm *fdm); From eb1ea2d80dd71c2799a961ca636722b74eb32286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 16:06:35 +0100 Subject: [PATCH 02/19] term: add visually focused attribute to terminal struct --- terminal.h | 1 + wayland.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/terminal.h b/terminal.h index a1c01942..e4eafe77 100644 --- a/terminal.h +++ b/terminal.h @@ -276,6 +276,7 @@ struct terminal { struct wayland *wl; struct wl_window *window; + bool visual_focus; struct { int scrollback_lines; diff --git a/wayland.c b/wayland.c index 380cc526..80300aba 100644 --- a/wayland.c +++ b/wayland.c @@ -411,12 +411,21 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, { LOG_DBG("xdg-toplevel: configure: %dx%d", width, height); - if (width <= 0 || height <= 0) - return; - struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); - render_resize(term, width, height); + + bool is_focused = false; + enum xdg_toplevel_state *state; + wl_array_for_each(state, states) { + if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) { + is_focused = true; + } + } + + term->visual_focus = is_focused; + + if (width >= 0 && height >= 0) + render_resize(term, width, height); } static void From 4a9f359a6a13c058e9c76b44941d4435065faa51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 17:25:41 +0100 Subject: [PATCH 03/19] wayland: ignore early configure calls At this point, not everything has been setup and we crash when trying to convert the surface pointer to a terminal pointer. --- wayland.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wayland.c b/wayland.c index 80300aba..e13e6b0b 100644 --- a/wayland.c +++ b/wayland.c @@ -411,6 +411,9 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, { LOG_DBG("xdg-toplevel: configure: %dx%d", width, height); + if (width == 0 && height == 0) + return; + struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); @@ -423,9 +426,7 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, } term->visual_focus = is_focused; - - if (width >= 0 && height >= 0) - render_resize(term, width, height); + render_resize(term, width, height); } static void From 2192d95fa9126012f7eeae9ac8382dd957b9ae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 17:38:50 +0100 Subject: [PATCH 04/19] wayland: xdg-toplevel-configure: check for stateless configure calls Ignore configure calls without state, instead of checking for width/height == 0. --- wayland.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/wayland.c b/wayland.c index e13e6b0b..99e98fe2 100644 --- a/wayland.c +++ b/wayland.c @@ -411,20 +411,23 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, { LOG_DBG("xdg-toplevel: configure: %dx%d", width, height); - if (width == 0 && height == 0) + bool stateless = true; + bool is_focused = false; + + enum xdg_toplevel_state *state; + wl_array_for_each(state, states) { + stateless = false; + + if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) + is_focused = true; + } + + if (stateless) return; struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); - bool is_focused = false; - enum xdg_toplevel_state *state; - wl_array_for_each(state, states) { - if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) { - is_focused = true; - } - } - term->visual_focus = is_focused; render_resize(term, width, height); } From e9325b958f6fb6416f77a1f0d9f8b049f6a6a46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 19:29:42 +0100 Subject: [PATCH 05/19] term: rename term_focus_{in,out} -> term_kbd_focus_{in,out} --- input.c | 4 ++-- terminal.c | 4 ++-- terminal.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/input.c b/input.c index ebbcac74..9df9c5dc 100644 --- a/input.c +++ b/input.c @@ -90,7 +90,7 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, wayl->kbd_focus = wayl_terminal_from_surface(wayl, surface); assert(wayl->kbd_focus != NULL); - term_focus_in(wayl->kbd_focus); + term_kbd_focus_in(wayl->kbd_focus); term_xcursor_update(wayl->kbd_focus); } @@ -157,7 +157,7 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, * keyboard_leave() (and keyboard_key()) without first having * received a keyboard_enter() */ - term_focus_out(old_focused); + term_kbd_focus_out(old_focused); term_xcursor_update(old_focused); } else { LOG_WARN( diff --git a/terminal.c b/terminal.c index a9ed686f..4e1dd201 100644 --- a/terminal.c +++ b/terminal.c @@ -1392,7 +1392,7 @@ term_restore_cursor(struct terminal *term) } void -term_focus_in(struct terminal *term) +term_kbd_focus_in(struct terminal *term) { if (term->cursor_blink.active) cursor_blink_start_timer(term); @@ -1404,7 +1404,7 @@ term_focus_in(struct terminal *term) } void -term_focus_out(struct terminal *term) +term_kbd_focus_out(struct terminal *term) { if (term->cursor_blink.active) cursor_blink_stop_timer(term); diff --git a/terminal.h b/terminal.h index e4eafe77..301ebad1 100644 --- a/terminal.h +++ b/terminal.h @@ -378,8 +378,8 @@ void term_arm_blink_timer(struct terminal *term); void term_restore_cursor(struct terminal *term); -void term_focus_in(struct terminal *term); -void term_focus_out(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); From 4be3c04999c821a601951dc47987dec1c8aa4a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 19:30:34 +0100 Subject: [PATCH 06/19] input: keyboard-leave: move comment to where it belongs --- input.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/input.c b/input.c index 9df9c5dc..7f81da8d 100644 --- a/input.c +++ b/input.c @@ -152,14 +152,14 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, stop_repeater(wayl, -1); if (old_focused != NULL) { + term_kbd_focus_out(old_focused); + term_xcursor_update(old_focused); + } else { /* * Sway bug - under certain conditions we get a * keyboard_leave() (and keyboard_key()) without first having * received a keyboard_enter() */ - term_kbd_focus_out(old_focused); - term_xcursor_update(old_focused); - } else { LOG_WARN( "compositor sent keyboard_leave event without a keyboard_enter " "event: surface=%p", surface); From 6f281cebfb5db24c10a2cd0a10e2175fe9f6b514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 19:35:32 +0100 Subject: [PATCH 07/19] term: add term_visual_focus_{in,out} These functions should be called when the terminal gets or loses visual focus. Note that this isn't necessarily the same as having keyboard focus. --- terminal.c | 25 +++++++++++++++++-------- terminal.h | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/terminal.c b/terminal.c index 4e1dd201..fe69890d 100644 --- a/terminal.c +++ b/terminal.c @@ -1392,27 +1392,36 @@ term_restore_cursor(struct terminal *term) } void -term_kbd_focus_in(struct terminal *term) +term_visual_focus_in(struct terminal *term) { + term->visual_focus = true; if (term->cursor_blink.active) cursor_blink_start_timer(term); + cursor_refresh(term); +} - if (term->focus_events) - term_to_slave(term, "\033[I", 3); +void +term_visual_focus_out(struct terminal *term) +{ + term->visual_focus = false; + if (term->cursor_blink.active) + cursor_blink_stop_timer(term); cursor_refresh(term); } +void +term_kbd_focus_in(struct terminal *term) +{ + if (term->focus_events) + term_to_slave(term, "\033[I", 3); +} + void term_kbd_focus_out(struct terminal *term) { - if (term->cursor_blink.active) - cursor_blink_stop_timer(term); - if (term->focus_events) term_to_slave(term, "\033[O", 3); - - cursor_refresh(term); } static int diff --git a/terminal.h b/terminal.h index 301ebad1..16323bfb 100644 --- a/terminal.h +++ b/terminal.h @@ -378,6 +378,8 @@ void term_arm_blink_timer(struct terminal *term); void term_restore_cursor(struct terminal *term); +void term_visual_focus_in(struct terminal *term); +void term_visual_focus_out(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); From 0e40e1c711134a600f7a410585a442edcf058db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 19:37:01 +0100 Subject: [PATCH 08/19] wayland: xdg-top-level-configure: call term_visual_focus_{in,out} --- wayland.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index 99e98fe2..7ab1ef2f 100644 --- a/wayland.c +++ b/wayland.c @@ -428,7 +428,11 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); - term->visual_focus = is_focused; + if (is_focused && !term->visual_focus) + term_visual_focus_in(term); + else if (!is_focused && term->visual_focus) + term_visual_focus_out(term); + render_resize(term, width, height); } From 29483f936f664a17fcf36f55350970dd3891fd10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Jan 2020 19:37:21 +0100 Subject: [PATCH 09/19] render: draw_cursor: use terminal's visual focus to determine cursor shape --- render.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/render.c b/render.c index d02ada3e..addb8d7a 100644 --- a/render.c +++ b/render.c @@ -279,8 +279,6 @@ draw_cursor(const struct terminal *term, const struct cell *cell, pixman_image_t *pix, pixman_color_t *fg, const pixman_color_t *bg, int x, int y, int cols) { - bool have_focus = term->wl->kbd_focus == term; - pixman_color_t cursor_color; pixman_color_t text_color; @@ -307,7 +305,7 @@ draw_cursor(const struct terminal *term, const struct cell *cell, switch (term->cursor_style) { case CURSOR_BLOCK: - if (!have_focus) + if (!term->visual_focus) draw_unfocused_block(term, pix, &cursor_color, x, y, cols); else if (term->cursor_blink.state == CURSOR_BLINK_ON) { @@ -319,12 +317,12 @@ draw_cursor(const struct terminal *term, const struct cell *cell, break; case CURSOR_BAR: - if (term->cursor_blink.state == CURSOR_BLINK_ON || !have_focus) + if (term->cursor_blink.state == CURSOR_BLINK_ON || !term->visual_focus) draw_bar(term, pix, font, &cursor_color, x, y); break; case CURSOR_UNDERLINE: - if (term->cursor_blink.state == CURSOR_BLINK_ON || !have_focus) { + if (term->cursor_blink.state == CURSOR_BLINK_ON || !term->visual_focus) { draw_underline( term, pix, attrs_to_font(term, &cell->attrs), &cursor_color, x, y, cols); From 4451f4ad62d4f5117f815e258e3c2cf4fa0fb758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 11:15:35 +0100 Subject: [PATCH 10/19] term: spell 'initialize' correctly --- terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index fe69890d..8a602925 100644 --- a/terminal.c +++ b/terminal.c @@ -653,7 +653,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, if ((term->slave = slave_spawn(term->ptmx, argc, term->cwd, argv, term_env, conf->shell)) == -1) goto err; - /* Initiailze the Wayland window backend */ + /* Initialize the Wayland window backend */ if ((term->window = wayl_win_init(wayl)) == NULL) goto err; From 913c684844ad41c8a4b803abd649a9460e3a57dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 11:16:06 +0100 Subject: [PATCH 11/19] term: term_init() calls wl_display_roundtrip() Instead of having `wayl_win_init()` call `wl_display_roundtrip()` (which it itself doesn't need), call it from `term_init()`. This allows us to add ourselves (the new terminal instance) to the terminal list in the wayland backend, before triggering the wayland events caused by `wayl_win_init()`. This is turn allows the wayland backend to find/lookup the new terminal when those events occur.. --- terminal.c | 7 ++++++- wayland.c | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index 8a602925..c3697720 100644 --- a/terminal.c +++ b/terminal.c @@ -657,6 +657,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, if ((term->window = wayl_win_init(wayl)) == NULL) goto err; + /* Let the Wayland backend know we exist */ + tll_push_back(wayl->terms, term); + + /* Roundtrip to ensure the wayland window have been configured */ + wl_display_roundtrip(term->wl->display); + term_set_window_title(term, "foot"); /* Try to use user-configured window dimentions */ @@ -675,7 +681,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, height = max(height, term->cell_height); render_resize(term, width, height); - tll_push_back(wayl->terms, term); return term; err: diff --git a/wayland.c b/wayland.c index 7ab1ef2f..816ef1b6 100644 --- a/wayland.c +++ b/wayland.c @@ -804,8 +804,6 @@ wayl_win_init(struct wayland *wayl) wl_subsurface_set_desync(win->search_sub_surface); wl_surface_commit(win->surface); - wl_display_roundtrip(wayl->display); - return win; out: From 304355d8edaf8259ff73d34955b006c8f1abd4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 11:18:43 +0100 Subject: [PATCH 12/19] wayland: xdg-toplevel-configure: no need to detect early configure events We can now lookup terminal instances at all times, making it unnecessary to detect "early" configure events. Note that we still need to prevent a resize from happening when width/height is 0. --- wayland.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/wayland.c b/wayland.c index 816ef1b6..0f54abb3 100644 --- a/wayland.c +++ b/wayland.c @@ -411,20 +411,14 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, { LOG_DBG("xdg-toplevel: configure: %dx%d", width, height); - bool stateless = true; bool is_focused = false; enum xdg_toplevel_state *state; wl_array_for_each(state, states) { - stateless = false; - if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) is_focused = true; } - if (stateless) - return; - struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); @@ -433,7 +427,8 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, else if (!is_focused && term->visual_focus) term_visual_focus_out(term); - render_resize(term, width, height); + if (width > 0 && height > 0) + render_resize(term, width, height); } static void From 80dfd5b6457a8f44be8b62af1e47284bb8e5c095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 11:19:56 +0100 Subject: [PATCH 13/19] term: visual_focus_{in,out}: do nothing if already focused/defocused --- terminal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/terminal.c b/terminal.c index c3697720..14cbf251 100644 --- a/terminal.c +++ b/terminal.c @@ -1399,6 +1399,9 @@ term_restore_cursor(struct terminal *term) void term_visual_focus_in(struct terminal *term) { + if (term->visual_focus) + return; + term->visual_focus = true; if (term->cursor_blink.active) cursor_blink_start_timer(term); @@ -1408,6 +1411,9 @@ term_visual_focus_in(struct terminal *term) void term_visual_focus_out(struct terminal *term) { + if (!term->visual_focus) + return; + term->visual_focus = false; if (term->cursor_blink.active) cursor_blink_stop_timer(term); From aa9e87ffb004e7e453a385d7a166e719c0ebec48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 11:20:13 +0100 Subject: [PATCH 14/19] wayland: term_visual_focus_{in,out} handles already being focused/defocused --- wayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 0f54abb3..b42711f3 100644 --- a/wayland.c +++ b/wayland.c @@ -422,9 +422,9 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); - if (is_focused && !term->visual_focus) + if (is_focused) term_visual_focus_in(term); - else if (!is_focused && term->visual_focus) + else term_visual_focus_out(term); if (width > 0 && height > 0) From af26f043fb507c6aa4b6d7cf5dea39f3b9d3b234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 12:44:29 +0100 Subject: [PATCH 15/19] render: resize() now only calls refresh() if asked to --- render.c | 5 +++-- render.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/render.c b/render.c index 47017ea4..139bedb9 100644 --- a/render.c +++ b/render.c @@ -960,7 +960,7 @@ reflow(struct row **new_grid, int new_cols, int new_rows, /* Move to terminal.c? */ void -render_resize(struct terminal *term, int width, int height) +render_resize(struct terminal *term, int width, int height, bool refresh) { int scale = -1; tll_foreach(term->window->on_outputs, it) { @@ -1083,7 +1083,8 @@ render_resize(struct terminal *term, int width, int height) term->render.last_cursor.cell = NULL; term_damage_view(term); - render_refresh(term); + if (refresh) + render_refresh(term); } void diff --git a/render.h b/render.h index ad6b6578..e3253074 100644 --- a/render.h +++ b/render.h @@ -6,7 +6,7 @@ struct font *attrs_to_font( const struct terminal *term, const struct attributes *attrs); void grid_render(struct terminal *term); -void render_resize(struct terminal *term, int width, int height); +void render_resize(struct terminal *term, int width, int height, bool refresh); void render_set_title(struct terminal *term, const char *title); void render_refresh(struct terminal *term); From 26c16a9a47a0fec437e31220733c1f559dfd33c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 12:45:16 +0100 Subject: [PATCH 16/19] wayland: render_resize() now takes a 'refresh' argument --- wayland.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wayland.c b/wayland.c index b42711f3..ea4b2d40 100644 --- a/wayland.c +++ b/wayland.c @@ -142,7 +142,9 @@ output_scale(void *data, struct wl_output *wl_output, int32_t factor) tll_foreach(mon->wayl->terms, it) { struct terminal *term = it->item; - render_resize(term, term->width / term->scale, term->height / term->scale); + int scale = term->scale; + + render_resize(term, term->width / scale, term->height / scale, true); wayl_reload_cursor_theme(mon->wayl, term); } } @@ -368,7 +370,8 @@ surface_enter(void *data, struct wl_surface *wl_surface, tll_push_back(term->window->on_outputs, &it->item); /* Resize, since scale-to-use may have changed */ - render_resize(term, term->width / term->scale, term->height / term->scale); + int scale = term->scale; + render_resize(term, term->width / scale, term->height / scale, true); wayl_reload_cursor_theme(wayl, term); return; } @@ -392,7 +395,8 @@ surface_leave(void *data, struct wl_surface *wl_surface, tll_remove(term->window->on_outputs, it); /* Resize, since scale-to-use may have changed */ - render_resize(term, term->width / term->scale, term->height / term->scale); + int scale = term->scale; + render_resize(term, term->width / scale, term->height / scale, true); wayl_reload_cursor_theme(wayl, term); return; } @@ -428,7 +432,7 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, term_visual_focus_out(term); if (width > 0 && height > 0) - render_resize(term, width, height); + render_resize(term, width, height, false); } static void From bd13c2c86a08189d6d5269616634a123f59bde9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 12:45:30 +0100 Subject: [PATCH 17/19] term: render_resize() now takes a 'refresh' argument --- terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index 14cbf251..b31d3867 100644 --- a/terminal.c +++ b/terminal.c @@ -679,7 +679,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, /* Don't go below a single cell */ width = max(width, term->cell_width); height = max(height, term->cell_height); - render_resize(term, width, height); + render_resize(term, width, height, true); return term; From c94da979fbe3d0267373717fc87654caa0bcfa72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 12:45:58 +0100 Subject: [PATCH 18/19] wayland: xdg-surface-configure: refresh terminal Any changes done in any of the configure events are ignored before we've ack:ed the configure event. In particular, this means the resize done in xdg-toplevel-configure isn't displayed until the next time we call render_refresh(). Unless we do something ourselves, this can take quite some time, since we're basically need the slave to write something. So, in xdg-surface-configure, *after* having ack:ed the configure event, call render_refresh() to make the changes done in xdg-toplevel-configure visible as soon as possible. --- wayland.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index ea4b2d40..76c2f5d3 100644 --- a/wayland.c +++ b/wayland.c @@ -453,8 +453,23 @@ static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { - //LOG_DBG("xdg-surface: configure"); + LOG_DBG("xdg-surface: configure"); xdg_surface_ack_configure(xdg_surface, serial); + + /* + * Changes done in e.g. xdg-toplevel-configure will be ignored + * since the 'configure' event hasn't been ack:ed yet. + * + * Unfortunately, *this* function is called *last*, meaning we + * have no way of acking the configure before we resize the + * terminal in xdg-toplevel-configure. + * + * So, refresh here, to ensure changes take effect as soon as possible. + */ + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_xdg_surface(wayl, xdg_surface); + if (term->width > 0 && term->height > 0) + render_refresh(term); } static const struct xdg_surface_listener xdg_surface_listener = { @@ -946,6 +961,19 @@ wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface) return NULL; } +struct terminal * +wayl_terminal_from_xdg_surface(struct wayland *wayl, + struct xdg_surface *surface) +{ + tll_foreach(wayl->terms, it) { + if (it->item->window->xdg_surface == surface) + return it->item; + } + + assert(false); + return NULL; +} + struct terminal * wayl_terminal_from_xdg_toplevel(struct wayland *wayl, struct xdg_toplevel *toplevel) From 8494cc808f01d699174e68648c742326cc4e1d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Jan 2020 12:49:04 +0100 Subject: [PATCH 19/19] wayland: debug log state changes in xdg-toplevel-configure --- wayland.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/wayland.c b/wayland.c index 76c2f5d3..87c0428a 100644 --- a/wayland.c +++ b/wayland.c @@ -413,16 +413,58 @@ static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { - LOG_DBG("xdg-toplevel: configure: %dx%d", width, height); - bool is_focused = false; +#if defined(_DEBUG) + char state_str[2048]; + int state_chars = 0; + + static const char *const strings[] = { + [XDG_TOPLEVEL_STATE_MAXIMIZED] = "maximized", + [XDG_TOPLEVEL_STATE_FULLSCREEN] = "fullscreen", + [XDG_TOPLEVEL_STATE_RESIZING] = "resizing", + [XDG_TOPLEVEL_STATE_ACTIVATED] = "activated", + [XDG_TOPLEVEL_STATE_TILED_LEFT] = "tiled:left", + [XDG_TOPLEVEL_STATE_TILED_RIGHT] = "tiled:right", + [XDG_TOPLEVEL_STATE_TILED_TOP] = "tiled:top", + [XDG_TOPLEVEL_STATE_TILED_BOTTOM] = "tiled:bottom", + }; +#endif enum xdg_toplevel_state *state; wl_array_for_each(state, states) { - if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) + switch (*state) { + case XDG_TOPLEVEL_STATE_ACTIVATED: is_focused = true; + break; + + case XDG_TOPLEVEL_STATE_MAXIMIZED: + case XDG_TOPLEVEL_STATE_FULLSCREEN: + case XDG_TOPLEVEL_STATE_RESIZING: + case XDG_TOPLEVEL_STATE_TILED_LEFT: + case XDG_TOPLEVEL_STATE_TILED_RIGHT: + case XDG_TOPLEVEL_STATE_TILED_TOP: + case XDG_TOPLEVEL_STATE_TILED_BOTTOM: + /* Ignored */ + break; + } + +#if defined(_DEBUG) + if (*state >= XDG_TOPLEVEL_STATE_MAXIMIZED && + *state <= XDG_TOPLEVEL_STATE_TILED_BOTTOM) + { + state_chars += snprintf( + &state_str[state_chars], sizeof(state_str) - state_chars, + "%s, ", strings[*state]); + } +#endif } + if (state_chars > 2) + state_str[state_chars - 2] = '\0'; + + LOG_DBG("xdg-toplevel: configure: size=%dx%d, states=%s", + width, height, state_str); + struct wayland *wayl = data; struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel);