diff --git a/input.c b/input.c index 975923a3..56da84d9 100644 --- a/input.c +++ b/input.c @@ -30,50 +30,50 @@ static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { - struct terminal *term = data; + struct wayland *wayl = data; char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); /* TODO: free old context + keymap */ - if (term->wl.kbd.xkb_compose_state != NULL) { - xkb_compose_state_unref(term->wl.kbd.xkb_compose_state); - term->wl.kbd.xkb_compose_state = NULL; + if (wayl->kbd.xkb_compose_state != NULL) { + xkb_compose_state_unref(wayl->kbd.xkb_compose_state); + wayl->kbd.xkb_compose_state = NULL; } - if (term->wl.kbd.xkb_compose_table != NULL) { - xkb_compose_table_unref(term->wl.kbd.xkb_compose_table); - term->wl.kbd.xkb_compose_table = NULL; + if (wayl->kbd.xkb_compose_table != NULL) { + xkb_compose_table_unref(wayl->kbd.xkb_compose_table); + wayl->kbd.xkb_compose_table = NULL; } - if (term->wl.kbd.xkb_keymap != NULL) { - xkb_keymap_unref(term->wl.kbd.xkb_keymap); - term->wl.kbd.xkb_keymap = NULL; + if (wayl->kbd.xkb_keymap != NULL) { + xkb_keymap_unref(wayl->kbd.xkb_keymap); + wayl->kbd.xkb_keymap = NULL; } - if (term->wl.kbd.xkb_state != NULL) { - xkb_state_unref(term->wl.kbd.xkb_state); - term->wl.kbd.xkb_state = NULL; + if (wayl->kbd.xkb_state != NULL) { + xkb_state_unref(wayl->kbd.xkb_state); + wayl->kbd.xkb_state = NULL; } - if (term->wl.kbd.xkb != NULL) { - xkb_context_unref(term->wl.kbd.xkb); - term->wl.kbd.xkb = NULL; + if (wayl->kbd.xkb != NULL) { + xkb_context_unref(wayl->kbd.xkb); + wayl->kbd.xkb = NULL; } - term->wl.kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - term->wl.kbd.xkb_keymap = xkb_keymap_new_from_string( - term->wl.kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, + wayl->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + wayl->kbd.xkb_keymap = xkb_keymap_new_from_string( + wayl->kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); /* TODO: initialize in enter? */ - term->wl.kbd.xkb_state = xkb_state_new(term->wl.kbd.xkb_keymap); + wayl->kbd.xkb_state = xkb_state_new(wayl->kbd.xkb_keymap); - term->wl.kbd.mod_shift = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Shift"); - term->wl.kbd.mod_alt = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Mod1") ; - term->wl.kbd.mod_ctrl = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Control"); - term->wl.kbd.mod_meta = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Mod4"); + wayl->kbd.mod_shift = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Shift"); + wayl->kbd.mod_alt = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod1") ; + wayl->kbd.mod_ctrl = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Control"); + wayl->kbd.mod_meta = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod4"); /* Compose (dead keys) */ - term->wl.kbd.xkb_compose_table = xkb_compose_table_new_from_locale( - term->wl.kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS); - term->wl.kbd.xkb_compose_state = xkb_compose_state_new( - term->wl.kbd.xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS); + wayl->kbd.xkb_compose_table = xkb_compose_table_new_from_locale( + wayl->kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS); + wayl->kbd.xkb_compose_state = xkb_compose_state_new( + wayl->kbd.xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS); munmap(map_str, size); close(fd); @@ -83,20 +83,22 @@ static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { - struct terminal *term = data; - term->input_serial = serial; - term_focus_in(term); + struct wayland *wayl = data; + wayl->input_serial = serial; + wayl->focused = wayl_terminal_from_surface(wayl, surface); + assert(wayl->focused != NULL); + term_focus_in(wayl->focused); } static bool -start_repeater(struct terminal *term, uint32_t key) +start_repeater(struct wayland *wayl, uint32_t key) { - if (term->wl.kbd.repeat.dont_re_repeat) + if (wayl->kbd.repeat.dont_re_repeat) return true; struct itimerspec t = { - .it_value = {.tv_sec = 0, .tv_nsec = term->wl.kbd.repeat.delay * 1000000}, - .it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / term->wl.kbd.repeat.rate}, + .it_value = {.tv_sec = 0, .tv_nsec = wayl->kbd.repeat.delay * 1000000}, + .it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / wayl->kbd.repeat.rate}, }; if (t.it_value.tv_nsec >= 1000000000) { @@ -107,22 +109,22 @@ start_repeater(struct terminal *term, uint32_t key) t.it_interval.tv_sec += t.it_interval.tv_nsec / 1000000000; t.it_interval.tv_nsec %= 1000000000; } - if (timerfd_settime(term->wl.kbd.repeat.fd, 0, &t, NULL) < 0) { + if (timerfd_settime(wayl->kbd.repeat.fd, 0, &t, NULL) < 0) { LOG_ERRNO("failed to arm keyboard repeat timer"); return false; } - term->wl.kbd.repeat.key = key; + wayl->kbd.repeat.key = key; return true; } static bool -stop_repeater(struct terminal *term, uint32_t key) +stop_repeater(struct wayland *wayl, uint32_t key) { - if (key != -1 && key != term->wl.kbd.repeat.key) + if (key != -1 && key != wayl->kbd.repeat.key) return true; - if (timerfd_settime(term->wl.kbd.repeat.fd, 0, &(struct itimerspec){{0}}, NULL) < 0) { + if (timerfd_settime(wayl->kbd.repeat.fd, 0, &(struct itimerspec){{0}}, NULL) < 0) { LOG_ERRNO("failed to disarm keyboard repeat timer"); return false; } @@ -134,30 +136,33 @@ static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface) { - struct terminal *term = data; + struct wayland *wayl = data; - stop_repeater(term, -1); - term_focus_out(term); + stop_repeater(wayl, -1); + term_focus_out(wayl->focused); + wayl->focused = NULL; } static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl->focused; + assert(term != NULL); - const xkb_mod_mask_t ctrl = 1 << term->wl.kbd.mod_ctrl; - const xkb_mod_mask_t alt = 1 << term->wl.kbd.mod_alt; - const xkb_mod_mask_t shift = 1 << term->wl.kbd.mod_shift; - const xkb_mod_mask_t meta = 1 << term->wl.kbd.mod_meta; + const xkb_mod_mask_t ctrl = 1 << wayl->kbd.mod_ctrl; + const xkb_mod_mask_t alt = 1 << wayl->kbd.mod_alt; + const xkb_mod_mask_t shift = 1 << wayl->kbd.mod_shift; + const xkb_mod_mask_t meta = 1 << wayl->kbd.mod_meta; if (state == XKB_KEY_UP) { - stop_repeater(term, key); + stop_repeater(wayl, key); return; } key += 8; - xkb_keysym_t sym = xkb_state_key_get_one_sym(term->wl.kbd.xkb_state, key); + xkb_keysym_t sym = xkb_state_key_get_one_sym(wayl->kbd.xkb_state, key); #if 0 char foo[100]; @@ -165,22 +170,22 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, LOG_INFO("%s", foo); #endif - xkb_compose_state_feed(term->wl.kbd.xkb_compose_state, sym); + xkb_compose_state_feed(wayl->kbd.xkb_compose_state, sym); enum xkb_compose_status compose_status = xkb_compose_state_get_status( - term->wl.kbd.xkb_compose_state); + wayl->kbd.xkb_compose_state); if (compose_status == XKB_COMPOSE_COMPOSING) return; xkb_mod_mask_t mods = xkb_state_serialize_mods( - term->wl.kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); - //xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(term->wl.kbd.xkb_state, key); + wayl->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); + //xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(wayl->kbd.xkb_state, key); xkb_mod_mask_t consumed = 0x0; xkb_mod_mask_t significant = ctrl | alt | shift | meta; xkb_mod_mask_t effective_mods = mods & ~consumed & significant; if (term->is_searching) { - start_repeater(term, key - 8); + start_repeater(wayl, key - 8); search_input(term, key, sym, effective_mods); return; } @@ -188,7 +193,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, #if 0 for (size_t i = 0; i < 32; i++) { if (mods & (1 << i)) { - LOG_INFO("%s", xkb_keymap_mod_get_name(term->wl.kbd.xkb_keymap, i)); + LOG_INFO("%s", xkb_keymap_mod_get_name(wayl->kbd.xkb_keymap, i)); } } #endif @@ -200,10 +205,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, bool found_map = false; enum modifier keymap_mods = MOD_NONE; - keymap_mods |= term->wl.kbd.shift ? MOD_SHIFT : MOD_NONE; - keymap_mods |= term->wl.kbd.alt ? MOD_ALT : MOD_NONE; - keymap_mods |= term->wl.kbd.ctrl ? MOD_CTRL : MOD_NONE; - keymap_mods |= term->wl.kbd.meta ? MOD_META : MOD_NONE; + keymap_mods |= wayl->kbd.shift ? MOD_SHIFT : MOD_NONE; + keymap_mods |= wayl->kbd.alt ? MOD_ALT : MOD_NONE; + keymap_mods |= wayl->kbd.ctrl ? MOD_CTRL : MOD_NONE; + keymap_mods |= wayl->kbd.meta ? MOD_META : MOD_NONE; if (effective_mods == shift) { if (sym == XKB_KEY_Page_Up) { @@ -268,11 +273,11 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (compose_status == XKB_COMPOSE_COMPOSED) { count = xkb_compose_state_get_utf8( - term->wl.kbd.xkb_compose_state, (char *)buf, sizeof(buf)); - xkb_compose_state_reset(term->wl.kbd.xkb_compose_state); + wayl->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); + xkb_compose_state_reset(wayl->kbd.xkb_compose_state); } else { count = xkb_state_key_get_utf8( - term->wl.kbd.xkb_state, key, (char *)buf, sizeof(buf)); + wayl->kbd.xkb_state, key, (char *)buf, sizeof(buf)); } if (count > 0) { @@ -324,7 +329,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, } } - start_repeater(term, key - 8); + start_repeater(wayl, key - 8); } static void @@ -332,33 +337,33 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - struct terminal *term = data; + struct wayland *wayl = data; LOG_DBG("modifiers: depressed=0x%x, latched=0x%x, locked=0x%x, group=%u", mods_depressed, mods_latched, mods_locked, group); xkb_state_update_mask( - term->wl.kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); + wayl->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); /* Update state of modifiers we're interrested in for e.g mouse events */ - term->wl.kbd.shift = xkb_state_mod_index_is_active( - term->wl.kbd.xkb_state, term->wl.kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); - term->wl.kbd.alt = xkb_state_mod_index_is_active( - term->wl.kbd.xkb_state, term->wl.kbd.mod_alt, XKB_STATE_MODS_DEPRESSED); - term->wl.kbd.ctrl = xkb_state_mod_index_is_active( - term->wl.kbd.xkb_state, term->wl.kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); - term->wl.kbd.meta = xkb_state_mod_index_is_active( - term->wl.kbd.xkb_state, term->wl.kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); + wayl->kbd.shift = xkb_state_mod_index_is_active( + wayl->kbd.xkb_state, wayl->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); + wayl->kbd.alt = xkb_state_mod_index_is_active( + wayl->kbd.xkb_state, wayl->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED); + wayl->kbd.ctrl = xkb_state_mod_index_is_active( + wayl->kbd.xkb_state, wayl->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); + wayl->kbd.meta = xkb_state_mod_index_is_active( + wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); } static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay) { - struct terminal *term = data; + struct wayland *wayl = data; LOG_DBG("keyboard repeat: rate=%d, delay=%d", rate, delay); - term->wl.kbd.repeat.rate = rate; - term->wl.kbd.repeat.delay = delay; + wayl->kbd.repeat.rate = rate; + wayl->kbd.repeat.delay = delay; } const struct wl_keyboard_listener keyboard_listener = { @@ -373,7 +378,7 @@ const struct wl_keyboard_listener keyboard_listener = { void input_repeat(struct terminal *term, uint32_t key) { - keyboard_key(term, NULL, 0, 0, key, XKB_KEY_DOWN); + keyboard_key(&term->wl, NULL, 0, 0, key, XKB_KEY_DOWN); } static void @@ -381,13 +386,16 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_surface(wayl, surface); + + wayl->moused = term; int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; - term->mouse.col = x / term->cell_width; - term->mouse.row = y / term->cell_height; + wayl->mouse.col = x / term->cell_width; + wayl->mouse.row = y / term->cell_height; render_update_cursor_surface(term); } @@ -396,13 +404,17 @@ static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { + struct wayland *wayl = data; + wayl->moused = NULL; } static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl->moused; + assert(term != NULL); int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; @@ -413,24 +425,24 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) return; - bool update_selection = term->mouse.button == BTN_LEFT; + bool update_selection = wayl->mouse.button == BTN_LEFT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) selection_update(term, col, row); - if (col == term->mouse.col && row == term->mouse.row) + if (col == wayl->mouse.col && row == wayl->mouse.row) return; - term->mouse.col = col; - term->mouse.row = row; + wayl->mouse.col = col; + wayl->mouse.row = row; if (update_selection && !update_selection_early) selection_update(term, col, row); term_mouse_motion( - term, term->mouse.button, term->mouse.row, term->mouse.col, - term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl); + term, wayl->mouse.button, wayl->mouse.row, wayl->mouse.col, + wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl); } static void @@ -439,7 +451,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, { LOG_DBG("BUTTON: button=%x, state=%u", button, state); - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl->moused; + assert(term != NULL); search_cancel(term); @@ -448,43 +462,43 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, /* Time since last click */ struct timeval now, since_last; gettimeofday(&now, NULL); - timersub(&now, &term->mouse.last_time, &since_last); + timersub(&now, &wayl->mouse.last_time, &since_last); /* Double- or triple click? */ - if (button == term->mouse.last_button && + if (button == wayl->mouse.last_button && since_last.tv_sec == 0 && since_last.tv_usec <= 300 * 1000) { - term->mouse.count++; + wayl->mouse.count++; } else - term->mouse.count = 1; + wayl->mouse.count = 1; if (button == BTN_LEFT) { - switch (term->mouse.count) { + switch (wayl->mouse.count) { case 1: - selection_start(term, term->mouse.col, term->mouse.row); + selection_start(term, wayl->mouse.col, wayl->mouse.row); break; case 2: - selection_mark_word(term, term->mouse.col, term->mouse.row, - term->wl.kbd.ctrl, serial); + selection_mark_word(term, wayl->mouse.col, wayl->mouse.row, + wayl->kbd.ctrl, serial); break; case 3: - selection_mark_row(term, term->mouse.row, serial); + selection_mark_row(term, wayl->mouse.row, serial); break; } } else { - if (term->mouse.count == 1 && button == BTN_MIDDLE && selection_enabled(term)) + if (wayl->mouse.count == 1 && button == BTN_MIDDLE && selection_enabled(term)) selection_from_primary(term); selection_cancel(term); } - term->mouse.button = button; /* For motion events */ - term->mouse.last_button = button; - term->mouse.last_time = now; - term_mouse_down(term, button, term->mouse.row, term->mouse.col, - term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl); + wayl->mouse.button = button; /* For motion events */ + wayl->mouse.last_button = button; + wayl->mouse.last_time = now; + term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col, + wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl); break; } @@ -494,16 +508,19 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, else selection_finalize(term, serial); - term->mouse.button = 0; /* For motion events */ - term_mouse_up(term, button, term->mouse.row, term->mouse.col, - term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl); + wayl->mouse.button = 0; /* For motion events */ + term_mouse_up(term, button, wayl->mouse.row, wayl->mouse.col, + wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl); break; } } static void -mouse_scroll(struct terminal *term, int amount) +mouse_scroll(struct wayland *wayl, int amount) { + struct terminal *term = wayl->moused; + assert(term != NULL); + int button = amount < 0 ? BTN_BACK : BTN_FORWARD; void (*scrollback)(struct terminal *term, int rows) @@ -520,15 +537,15 @@ mouse_scroll(struct terminal *term, int amount) */ xkb_keycode_t key = xkb_keymap_key_by_name( - term->wl.kbd.xkb_keymap, button == BTN_BACK ? "UP" : "DOWN"); + wayl->kbd.xkb_keymap, button == BTN_BACK ? "UP" : "DOWN"); for (int i = 0; i < amount; i++) - keyboard_key(term, NULL, term->input_serial, 0, key - 8, XKB_KEY_DOWN); - keyboard_key(term, NULL, term->input_serial, 0, key - 8, XKB_KEY_UP); + keyboard_key(term, NULL, wayl->input_serial, 0, key - 8, XKB_KEY_DOWN); + keyboard_key(term, NULL, wayl->input_serial, 0, key - 8, XKB_KEY_UP); } else { for (int i = 0; i < amount; i++) - term_mouse_down(term, button, term->mouse.row, term->mouse.col, - term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl); + term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col, + wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl); scrollback(term, amount); } @@ -541,11 +558,12 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; - struct terminal *term = data; - if (term->mouse.have_discrete) + struct wayland *wayl = data; + + if (wayl->mouse.have_discrete) return; - mouse_scroll(term, wl_fixed_to_int(value)); + mouse_scroll(wayl, wl_fixed_to_int(value)); } static void @@ -555,16 +573,16 @@ wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; - struct terminal *term = data; - term->mouse.have_discrete = true; - mouse_scroll(term, discrete); + struct wayland *wayl = data; + wayl->mouse.have_discrete = true; + mouse_scroll(wayl, discrete); } static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { - struct terminal *term = data; - term->mouse.have_discrete = false; + struct wayland *wayl = data; + wayl->mouse.have_discrete = false; } static void diff --git a/main.c b/main.c index c1043171..b70b8420 100644 --- a/main.c +++ b/main.c @@ -49,9 +49,9 @@ static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { - struct terminal *term = data; + struct wayland *wayl = data; if (format == WL_SHM_FORMAT_ARGB8888) - term->wl.have_argb8888 = true; + wayl->have_argb8888 = true; } static const struct wl_shm_listener shm_listener = { @@ -73,26 +73,26 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { - struct terminal *term = data; + struct wayland *wayl = data; - if (term->wl.keyboard != NULL) { - wl_keyboard_release(term->wl.keyboard); - term->wl.keyboard = NULL; + if (wayl->keyboard != NULL) { + wl_keyboard_release(wayl->keyboard); + wayl->keyboard = NULL; } - if (term->wl.pointer.pointer != NULL) { - wl_pointer_release(term->wl.pointer.pointer); - term->wl.pointer.pointer = NULL; + if (wayl->pointer.pointer != NULL) { + wl_pointer_release(wayl->pointer.pointer); + wayl->pointer.pointer = NULL; } if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { - term->wl.keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(term->wl.keyboard, &keyboard_listener, term); + wayl->keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(wayl->keyboard, &keyboard_listener, wayl); } if (caps & WL_SEAT_CAPABILITY_POINTER) { - term->wl.pointer.pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(term->wl.pointer.pointer, &pointer_listener, term); + wayl->pointer.pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(wayl->pointer.pointer, &pointer_listener, wayl); } } @@ -137,10 +137,12 @@ static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct monitor *mon = data; + struct terminal *term = mon->wayl->term; + mon->scale = factor; - render_resize(mon->term, mon->term->width / mon->term->scale, mon->term->height / mon->term->scale); - render_reload_cursor_theme(mon->term); + render_resize(term, term->width / term->scale, term->height / term->scale); + render_reload_cursor_theme(term); } static const struct wl_output_listener output_listener = { @@ -200,72 +202,71 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { LOG_DBG("global: %s, version=%u", interface, version); - struct terminal *term = data; + struct wayland *wayl = data; if (strcmp(interface, wl_compositor_interface.name) == 0) { - term->wl.compositor = wl_registry_bind( - term->wl.registry, name, &wl_compositor_interface, 4); + wayl->compositor = wl_registry_bind( + wayl->registry, name, &wl_compositor_interface, 4); } else if (strcmp(interface, wl_subcompositor_interface.name) == 0) { - term->wl.sub_compositor = wl_registry_bind( - term->wl.registry, name, &wl_subcompositor_interface, 1); + wayl->sub_compositor = wl_registry_bind( + wayl->registry, name, &wl_subcompositor_interface, 1); } else if (strcmp(interface, wl_shm_interface.name) == 0) { - term->wl.shm = wl_registry_bind( - term->wl.registry, name, &wl_shm_interface, 1); - wl_shm_add_listener(term->wl.shm, &shm_listener, term); - wl_display_roundtrip(term->wl.display); + wayl->shm = wl_registry_bind( + wayl->registry, name, &wl_shm_interface, 1); + wl_shm_add_listener(wayl->shm, &shm_listener, wayl); + wl_display_roundtrip(wayl->display); } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - term->window.shell = wl_registry_bind( - term->wl.registry, name, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(term->window.shell, &xdg_wm_base_listener, term); + wayl->shell = wl_registry_bind( + wayl->registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(wayl->shell, &xdg_wm_base_listener, wayl); } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) - term->window.xdg_decoration_manager = wl_registry_bind( - term->wl.registry, name, &zxdg_decoration_manager_v1_interface, 1); + wayl->xdg_decoration_manager = wl_registry_bind( + wayl->registry, name, &zxdg_decoration_manager_v1_interface, 1); else if (strcmp(interface, wl_seat_interface.name) == 0) { - term->wl.seat = wl_registry_bind( - term->wl.registry, name, &wl_seat_interface, 5); - wl_seat_add_listener(term->wl.seat, &seat_listener, term); - wl_display_roundtrip(term->wl.display); + wayl->seat = wl_registry_bind( + wayl->registry, name, &wl_seat_interface, 5); + wl_seat_add_listener(wayl->seat, &seat_listener, wayl); + wl_display_roundtrip(wayl->display); } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { - term->wl.xdg_output_manager = wl_registry_bind( - term->wl.registry, name, &zxdg_output_manager_v1_interface, min(version, 2)); + wayl->xdg_output_manager = wl_registry_bind( + wayl->registry, name, &zxdg_output_manager_v1_interface, min(version, 2)); } else if (strcmp(interface, wl_output_interface.name) == 0) { struct wl_output *output = wl_registry_bind( - term->wl.registry, name, &wl_output_interface, 3); + wayl->registry, name, &wl_output_interface, 3); tll_push_back( - term->wl.monitors, ((struct monitor){ - .term = term, .output = output})); + wayl->monitors, ((struct monitor){.wayl = wayl, .output = output})); - struct monitor *mon = &tll_back(term->wl.monitors); + struct monitor *mon = &tll_back(wayl->monitors); wl_output_add_listener(output, &output_listener, mon); mon->xdg = zxdg_output_manager_v1_get_xdg_output( - term->wl.xdg_output_manager, mon->output); + wayl->xdg_output_manager, mon->output); zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon); - wl_display_roundtrip(term->wl.display); + wl_display_roundtrip(wayl->display); } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { - term->wl.data_device_manager = wl_registry_bind( - term->wl.registry, name, &wl_data_device_manager_interface, 1); + wayl->data_device_manager = wl_registry_bind( + wayl->registry, name, &wl_data_device_manager_interface, 1); } else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) { - term->wl.primary_selection_device_manager = wl_registry_bind( - term->wl.registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); + wayl->primary_selection_device_manager = wl_registry_bind( + wayl->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); } } @@ -273,8 +274,10 @@ static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { - struct terminal *term = data; - tll_foreach(term->wl.monitors, it) { + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_surface(wayl, wl_surface); + + tll_foreach(wayl->monitors, it) { if (it->item.output == wl_output) { LOG_DBG("mapped on %s", it->item.name); tll_push_back(term->window.on_outputs, &it->item); @@ -293,7 +296,9 @@ static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_surface(wayl, wl_surface); + tll_foreach(term->window.on_outputs, it) { if (it->item->output != wl_output) continue; @@ -324,17 +329,20 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, if (width <= 0 || height <= 0) return; - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); render_resize(term, width, height); } static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { - struct terminal *term = data; + struct wayland *wayl = data; + struct terminal *term = wayl_terminal_from_xdg_toplevel(wayl, xdg_toplevel); LOG_DBG("xdg-toplevel: close"); + term->quit = true; - wl_display_roundtrip(term->wl.display); + wl_display_roundtrip(wayl->display); } static const struct xdg_toplevel_listener xdg_toplevel_listener = { @@ -393,15 +401,15 @@ static const struct wl_registry_listener registry_listener = { static bool fdm_wayl(struct fdm *fdm, int fd, int events, void *data) { - struct terminal *term = data; - int event_count = wl_display_dispatch(term->wl.display); + struct wayland *wayl = data; + int event_count = wl_display_dispatch(wayl->display); if (events & EPOLLHUP) { LOG_ERR("disconnected from Wayland"); return false; } - return event_count != -1 && !term->quit; + return event_count != -1 && !wayl->term->quit; } static bool @@ -900,7 +908,7 @@ main(int argc, char *const *argv) goto out; } - wl_registry_add_listener(term.wl.registry, ®istry_listener, &term); + wl_registry_add_listener(term.wl.registry, ®istry_listener, &term.wl); wl_display_roundtrip(term.wl.display); if (term.wl.compositor == NULL) { @@ -911,7 +919,7 @@ main(int argc, char *const *argv) LOG_ERR("no shared memory buffers interface"); goto out; } - if (term.window.shell == NULL) { + if (term.wl.shell == NULL) { LOG_ERR("no XDG shell interface"); goto out; } @@ -940,14 +948,14 @@ main(int argc, char *const *argv) /* Clipboard */ term.wl.data_device = wl_data_device_manager_get_data_device( term.wl.data_device_manager, term.wl.seat); - wl_data_device_add_listener(term.wl.data_device, &data_device_listener, &term); + wl_data_device_add_listener(term.wl.data_device, &data_device_listener, &term.wl); /* Primary selection */ if (term.wl.primary_selection_device_manager != NULL) { term.wl.primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( term.wl.primary_selection_device_manager, term.wl.seat); zwp_primary_selection_device_v1_add_listener( - term.wl.primary_selection_device, &primary_selection_device_listener, &term); + term.wl.primary_selection_device, &primary_selection_device_listener, &term.wl); } /* Cursor */ @@ -981,24 +989,24 @@ main(int argc, char *const *argv) goto out; } - wl_surface_add_listener(term.window.surface, &surface_listener, &term); + wl_surface_add_listener(term.window.surface, &surface_listener, &term.wl); - term.window.xdg_surface = xdg_wm_base_get_xdg_surface(term.window.shell, term.window.surface); - xdg_surface_add_listener(term.window.xdg_surface, &xdg_surface_listener, &term); + term.window.xdg_surface = xdg_wm_base_get_xdg_surface(term.wl.shell, term.window.surface); + xdg_surface_add_listener(term.window.xdg_surface, &xdg_surface_listener, &term.wl); term.window.xdg_toplevel = xdg_surface_get_toplevel(term.window.xdg_surface); - xdg_toplevel_add_listener(term.window.xdg_toplevel, &xdg_toplevel_listener, &term); + xdg_toplevel_add_listener(term.window.xdg_toplevel, &xdg_toplevel_listener, &term.wl); xdg_toplevel_set_app_id(term.window.xdg_toplevel, "foot"); term_set_window_title(&term, "foot"); /* Request server-side decorations */ term.window.xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - term.window.xdg_decoration_manager, term.window.xdg_toplevel); + term.wl.xdg_decoration_manager, term.window.xdg_toplevel); zxdg_toplevel_decoration_v1_set_mode( term.window.xdg_toplevel_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); zxdg_toplevel_decoration_v1_add_listener( - term.window.xdg_toplevel_decoration, &xdg_toplevel_decoration_listener, &term); + term.window.xdg_toplevel_decoration, &xdg_toplevel_decoration_listener, &term.wl); /* Scrollback search box */ term.window.search_surface = wl_compositor_create_surface(term.wl.compositor); @@ -1109,7 +1117,7 @@ main(int argc, char *const *argv) if ((fdm = fdm_init()) == NULL) goto out; - fdm_add(fdm, wl_display_get_fd(term.wl.display), EPOLLIN, &fdm_wayl, &term); + fdm_add(fdm, wl_display_get_fd(term.wl.display), EPOLLIN, &fdm_wayl, &term.wl); fdm_add(fdm, term.ptmx, EPOLLIN, &fdm_ptmx, &term); fdm_add(fdm, term.wl.kbd.repeat.fd, EPOLLIN, &fdm_repeat, &term); fdm_add(fdm, term.flash.fd, EPOLLIN, &fdm_flash, &term); diff --git a/osc.c b/osc.c index 694547c8..b506f0bb 100644 --- a/osc.c +++ b/osc.c @@ -30,14 +30,14 @@ osc_to_clipboard(struct terminal *term, const char *target, switch (*t) { case 'c': { char *copy = strdup(decoded); - if (!text_to_clipboard(term, copy, term->input_serial)) + if (!text_to_clipboard(term, copy, term->wl.input_serial)) free(copy); break; } case 'p': { char *copy = strdup(decoded); - if (!text_to_primary(term, copy, term->input_serial)) + if (!text_to_primary(term, copy, term->wl.input_serial)) free(copy); break; } @@ -130,7 +130,7 @@ osc_from_clipboard(struct terminal *term, const char *source) switch (src) { case 'c': - text_from_clipboard(term, term->input_serial, &from_clipboard_cb, &ctx); + text_from_clipboard(term, term->wl.input_serial, &from_clipboard_cb, &ctx); break; case 'p': diff --git a/search.c b/search.c index e9da3770..5c0ce1b7 100644 --- a/search.c +++ b/search.c @@ -317,7 +317,7 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask /* "Commit" search - copy selection to primary and cancel search */ else if (mods == 0 && sym == XKB_KEY_Return) { - selection_finalize(term, term->input_serial); + selection_finalize(term, term->wl.input_serial); search_cancel_keep_selection(term); return; } diff --git a/selection.c b/selection.c index 33875e94..a3c88307 100644 --- a/selection.c +++ b/selection.c @@ -742,8 +742,8 @@ selection(void *data, struct wl_data_device *wl_data_device, { /* Selection offer from other client */ - struct terminal *term = data; - struct wl_clipboard *clipboard = &term->wl.clipboard; + struct wayland *wayl = data; + struct wl_clipboard *clipboard = &wayl->clipboard; if (clipboard->data_offer != NULL) wl_data_offer_destroy(clipboard->data_offer); @@ -791,8 +791,8 @@ primary_selection(void *data, { /* Selection offer from other client, for primary */ - struct terminal *term = data; - struct wl_primary *primary = &term->wl.primary; + struct wayland *wayl = data; + struct wl_primary *primary = &wayl->primary; if (primary->data_offer != NULL) zwp_primary_selection_offer_v1_destroy(primary->data_offer); diff --git a/terminal.h b/terminal.h index cd8d7768..7d7d1fcd 100644 --- a/terminal.h +++ b/terminal.h @@ -200,19 +200,6 @@ struct terminal { uint32_t default_table[256]; } colors; - struct { - int col; - int row; - int button; - - int count; - int last_button; - struct timeval last_time; - - /* We used a discrete axis event in the current pointer frame */ - bool have_discrete; - } mouse; - struct coord cursor; struct coord saved_cursor; struct coord alt_saved_cursor; @@ -228,7 +215,6 @@ struct terminal { uint32_t cursor; } cursor_color; - uint32_t input_serial; struct { struct coord start; struct coord end; diff --git a/wayland.c b/wayland.c index e6701de6..c3d7657f 100644 --- a/wayland.c +++ b/wayland.c @@ -13,6 +13,7 @@ #include "log.h" #include "tllist.h" +#include "terminal.h" void wayl_init(struct wayland *wayl) @@ -33,6 +34,11 @@ wayl_destroy(struct wayland *wayl) if (wayl->xdg_output_manager != NULL) zxdg_output_manager_v1_destroy(wayl->xdg_output_manager); + if (wayl->shell != NULL) + xdg_wm_base_destroy(wayl->shell); + + if (wayl->xdg_decoration_manager != NULL) + zxdg_decoration_manager_v1_destroy(wayl->xdg_decoration_manager); if (wayl->kbd.xkb_compose_state != NULL) xkb_compose_state_unref(wayl->kbd.xkb_compose_state); @@ -99,14 +105,25 @@ wayl_win_destroy(struct wl_window *win) wl_callback_destroy(win->frame_callback); if (win->xdg_toplevel_decoration != NULL) zxdg_toplevel_decoration_v1_destroy(win->xdg_toplevel_decoration); - if (win->xdg_decoration_manager != NULL) - zxdg_decoration_manager_v1_destroy(win->xdg_decoration_manager); if (win->xdg_toplevel != NULL) xdg_toplevel_destroy(win->xdg_toplevel); if (win->xdg_surface != NULL) xdg_surface_destroy(win->xdg_surface); - if (win->shell != NULL) - xdg_wm_base_destroy(win->shell); if (win->surface != NULL) wl_surface_destroy(win->surface); } + +struct terminal * +wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface) +{ + assert(surface == wayl->term->window.surface); + return wayl->term; +} + +struct terminal * +wayl_terminal_from_xdg_toplevel(struct wayland *wayl, + struct xdg_toplevel *toplevel) +{ + assert(toplevel == wayl->term->window.xdg_toplevel); + return wayl->term; +} diff --git a/wayland.h b/wayland.h index 43c4179f..9b02b84e 100644 --- a/wayland.h +++ b/wayland.h @@ -10,7 +10,8 @@ #include "tllist.h" struct monitor { - struct terminal *term; + //struct terminal *term; + struct wayland *wayl; struct wl_output *output; struct zxdg_output_v1 *xdg; char *name; @@ -71,11 +72,9 @@ struct wl_primary { struct wl_window { struct wl_surface *surface; - struct xdg_wm_base *shell; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; - struct zxdg_decoration_manager_v1 *xdg_decoration_manager; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; /* Scrollback search */ @@ -99,10 +98,14 @@ struct wayland { struct wl_keyboard *keyboard; struct zxdg_output_manager_v1 *xdg_output_manager; + struct xdg_wm_base *shell; + struct zxdg_decoration_manager_v1 *xdg_decoration_manager; + /* Keyboard */ struct kbd kbd; /* Clipboard */ + uint32_t input_serial; struct wl_data_device_manager *data_device_manager; struct wl_data_device *data_device; struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager; @@ -123,15 +126,37 @@ struct wayland { char *theme_name; } pointer; + struct { + int col; + int row; + int button; + + int count; + int last_button; + struct timeval last_time; + + /* We used a discrete axis event in the current pointer frame */ + bool have_discrete; + } mouse; + bool have_argb8888; tll(struct monitor) monitors; /* All available outputs */ /* TODO: turn into a list to support multiple windows */ struct terminal *term; + struct terminal *focused; + struct terminal *moused; }; /* TODO: return allocated pointer */ void wayl_init(struct wayland *wayl); void wayl_destroy(struct wayland *wayl); +struct terminal *wayl_terminal_from_surface( + struct wayland *wayl, struct wl_surface *surface); +struct terminal *wayl_terminal_from_xdg_surface( + struct wayland *wayl, struct xdg_surface *surface); +struct terminal *wayl_terminal_from_xdg_toplevel( + struct wayland *wayl, struct xdg_toplevel *toplevel); + void wayl_win_destroy(struct wl_window *win);