mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
wayland: change all wayland callbacks to take a wayland pointer
Instead of passing the terminal to the wayland callbacks, pass a 'struct wayland' pointer.
This commit is contained in:
parent
eda04d0560
commit
9f0b1f94c2
8 changed files with 269 additions and 215 deletions
260
input.c
260
input.c
|
|
@ -30,50 +30,50 @@ static void
|
||||||
keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
uint32_t format, int32_t fd, uint32_t size)
|
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);
|
char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
|
||||||
/* TODO: free old context + keymap */
|
/* TODO: free old context + keymap */
|
||||||
if (term->wl.kbd.xkb_compose_state != NULL) {
|
if (wayl->kbd.xkb_compose_state != NULL) {
|
||||||
xkb_compose_state_unref(term->wl.kbd.xkb_compose_state);
|
xkb_compose_state_unref(wayl->kbd.xkb_compose_state);
|
||||||
term->wl.kbd.xkb_compose_state = NULL;
|
wayl->kbd.xkb_compose_state = NULL;
|
||||||
}
|
}
|
||||||
if (term->wl.kbd.xkb_compose_table != NULL) {
|
if (wayl->kbd.xkb_compose_table != NULL) {
|
||||||
xkb_compose_table_unref(term->wl.kbd.xkb_compose_table);
|
xkb_compose_table_unref(wayl->kbd.xkb_compose_table);
|
||||||
term->wl.kbd.xkb_compose_table = NULL;
|
wayl->kbd.xkb_compose_table = NULL;
|
||||||
}
|
}
|
||||||
if (term->wl.kbd.xkb_keymap != NULL) {
|
if (wayl->kbd.xkb_keymap != NULL) {
|
||||||
xkb_keymap_unref(term->wl.kbd.xkb_keymap);
|
xkb_keymap_unref(wayl->kbd.xkb_keymap);
|
||||||
term->wl.kbd.xkb_keymap = NULL;
|
wayl->kbd.xkb_keymap = NULL;
|
||||||
}
|
}
|
||||||
if (term->wl.kbd.xkb_state != NULL) {
|
if (wayl->kbd.xkb_state != NULL) {
|
||||||
xkb_state_unref(term->wl.kbd.xkb_state);
|
xkb_state_unref(wayl->kbd.xkb_state);
|
||||||
term->wl.kbd.xkb_state = NULL;
|
wayl->kbd.xkb_state = NULL;
|
||||||
}
|
}
|
||||||
if (term->wl.kbd.xkb != NULL) {
|
if (wayl->kbd.xkb != NULL) {
|
||||||
xkb_context_unref(term->wl.kbd.xkb);
|
xkb_context_unref(wayl->kbd.xkb);
|
||||||
term->wl.kbd.xkb = NULL;
|
wayl->kbd.xkb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
term->wl.kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
wayl->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
term->wl.kbd.xkb_keymap = xkb_keymap_new_from_string(
|
wayl->kbd.xkb_keymap = xkb_keymap_new_from_string(
|
||||||
term->wl.kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1,
|
wayl->kbd.xkb, map_str, XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
/* TODO: initialize in enter? */
|
/* 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");
|
wayl->kbd.mod_shift = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Shift");
|
||||||
term->wl.kbd.mod_alt = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Mod1") ;
|
wayl->kbd.mod_alt = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod1") ;
|
||||||
term->wl.kbd.mod_ctrl = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Control");
|
wayl->kbd.mod_ctrl = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Control");
|
||||||
term->wl.kbd.mod_meta = xkb_keymap_mod_get_index(term->wl.kbd.xkb_keymap, "Mod4");
|
wayl->kbd.mod_meta = xkb_keymap_mod_get_index(wayl->kbd.xkb_keymap, "Mod4");
|
||||||
|
|
||||||
/* Compose (dead keys) */
|
/* Compose (dead keys) */
|
||||||
term->wl.kbd.xkb_compose_table = xkb_compose_table_new_from_locale(
|
wayl->kbd.xkb_compose_table = xkb_compose_table_new_from_locale(
|
||||||
term->wl.kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS);
|
wayl->kbd.xkb, setlocale(LC_CTYPE, NULL), XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||||
term->wl.kbd.xkb_compose_state = xkb_compose_state_new(
|
wayl->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_STATE_NO_FLAGS);
|
||||||
|
|
||||||
munmap(map_str, size);
|
munmap(map_str, size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
@ -83,20 +83,22 @@ static void
|
||||||
keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
struct wl_surface *surface, struct wl_array *keys)
|
struct wl_surface *surface, struct wl_array *keys)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
term->input_serial = serial;
|
wayl->input_serial = serial;
|
||||||
term_focus_in(term);
|
wayl->focused = wayl_terminal_from_surface(wayl, surface);
|
||||||
|
assert(wayl->focused != NULL);
|
||||||
|
term_focus_in(wayl->focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
return true;
|
||||||
|
|
||||||
struct itimerspec t = {
|
struct itimerspec t = {
|
||||||
.it_value = {.tv_sec = 0, .tv_nsec = term->wl.kbd.repeat.delay * 1000000},
|
.it_value = {.tv_sec = 0, .tv_nsec = wayl->kbd.repeat.delay * 1000000},
|
||||||
.it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / term->wl.kbd.repeat.rate},
|
.it_interval = {.tv_sec = 0, .tv_nsec = 1000000000 / wayl->kbd.repeat.rate},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (t.it_value.tv_nsec >= 1000000000) {
|
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_sec += t.it_interval.tv_nsec / 1000000000;
|
||||||
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");
|
LOG_ERRNO("failed to arm keyboard repeat timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
term->wl.kbd.repeat.key = key;
|
wayl->kbd.repeat.key = key;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
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");
|
LOG_ERRNO("failed to disarm keyboard repeat timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -134,30 +136,33 @@ static void
|
||||||
keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
struct wl_surface *surface)
|
struct wl_surface *surface)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
|
|
||||||
stop_repeater(term, -1);
|
stop_repeater(wayl, -1);
|
||||||
term_focus_out(term);
|
term_focus_out(wayl->focused);
|
||||||
|
wayl->focused = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
uint32_t time, uint32_t key, uint32_t state)
|
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 ctrl = 1 << wayl->kbd.mod_ctrl;
|
||||||
const xkb_mod_mask_t alt = 1 << term->wl.kbd.mod_alt;
|
const xkb_mod_mask_t alt = 1 << wayl->kbd.mod_alt;
|
||||||
const xkb_mod_mask_t shift = 1 << term->wl.kbd.mod_shift;
|
const xkb_mod_mask_t shift = 1 << wayl->kbd.mod_shift;
|
||||||
const xkb_mod_mask_t meta = 1 << term->wl.kbd.mod_meta;
|
const xkb_mod_mask_t meta = 1 << wayl->kbd.mod_meta;
|
||||||
|
|
||||||
if (state == XKB_KEY_UP) {
|
if (state == XKB_KEY_UP) {
|
||||||
stop_repeater(term, key);
|
stop_repeater(wayl, key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key += 8;
|
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
|
#if 0
|
||||||
char foo[100];
|
char foo[100];
|
||||||
|
|
@ -165,22 +170,22 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
LOG_INFO("%s", foo);
|
LOG_INFO("%s", foo);
|
||||||
#endif
|
#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(
|
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)
|
if (compose_status == XKB_COMPOSE_COMPOSING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xkb_mod_mask_t mods = xkb_state_serialize_mods(
|
xkb_mod_mask_t mods = xkb_state_serialize_mods(
|
||||||
term->wl.kbd.xkb_state, XKB_STATE_MODS_DEPRESSED);
|
wayl->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||||
//xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods(term->wl.kbd.xkb_state, key);
|
//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 consumed = 0x0;
|
||||||
xkb_mod_mask_t significant = ctrl | alt | shift | meta;
|
xkb_mod_mask_t significant = ctrl | alt | shift | meta;
|
||||||
xkb_mod_mask_t effective_mods = mods & ~consumed & significant;
|
xkb_mod_mask_t effective_mods = mods & ~consumed & significant;
|
||||||
|
|
||||||
if (term->is_searching) {
|
if (term->is_searching) {
|
||||||
start_repeater(term, key - 8);
|
start_repeater(wayl, key - 8);
|
||||||
search_input(term, key, sym, effective_mods);
|
search_input(term, key, sym, effective_mods);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -188,7 +193,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
#if 0
|
#if 0
|
||||||
for (size_t i = 0; i < 32; i++) {
|
for (size_t i = 0; i < 32; i++) {
|
||||||
if (mods & (1 << 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
|
#endif
|
||||||
|
|
@ -200,10 +205,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
bool found_map = false;
|
bool found_map = false;
|
||||||
|
|
||||||
enum modifier keymap_mods = MOD_NONE;
|
enum modifier keymap_mods = MOD_NONE;
|
||||||
keymap_mods |= term->wl.kbd.shift ? MOD_SHIFT : MOD_NONE;
|
keymap_mods |= wayl->kbd.shift ? MOD_SHIFT : MOD_NONE;
|
||||||
keymap_mods |= term->wl.kbd.alt ? MOD_ALT : MOD_NONE;
|
keymap_mods |= wayl->kbd.alt ? MOD_ALT : MOD_NONE;
|
||||||
keymap_mods |= term->wl.kbd.ctrl ? MOD_CTRL : MOD_NONE;
|
keymap_mods |= wayl->kbd.ctrl ? MOD_CTRL : MOD_NONE;
|
||||||
keymap_mods |= term->wl.kbd.meta ? MOD_META : MOD_NONE;
|
keymap_mods |= wayl->kbd.meta ? MOD_META : MOD_NONE;
|
||||||
|
|
||||||
if (effective_mods == shift) {
|
if (effective_mods == shift) {
|
||||||
if (sym == XKB_KEY_Page_Up) {
|
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) {
|
if (compose_status == XKB_COMPOSE_COMPOSED) {
|
||||||
count = xkb_compose_state_get_utf8(
|
count = xkb_compose_state_get_utf8(
|
||||||
term->wl.kbd.xkb_compose_state, (char *)buf, sizeof(buf));
|
wayl->kbd.xkb_compose_state, (char *)buf, sizeof(buf));
|
||||||
xkb_compose_state_reset(term->wl.kbd.xkb_compose_state);
|
xkb_compose_state_reset(wayl->kbd.xkb_compose_state);
|
||||||
} else {
|
} else {
|
||||||
count = xkb_state_key_get_utf8(
|
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) {
|
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
|
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_depressed, uint32_t mods_latched,
|
||||||
uint32_t mods_locked, uint32_t group)
|
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",
|
LOG_DBG("modifiers: depressed=0x%x, latched=0x%x, locked=0x%x, group=%u",
|
||||||
mods_depressed, mods_latched, mods_locked, group);
|
mods_depressed, mods_latched, mods_locked, group);
|
||||||
|
|
||||||
xkb_state_update_mask(
|
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 */
|
/* Update state of modifiers we're interrested in for e.g mouse events */
|
||||||
term->wl.kbd.shift = xkb_state_mod_index_is_active(
|
wayl->kbd.shift = xkb_state_mod_index_is_active(
|
||||||
term->wl.kbd.xkb_state, term->wl.kbd.mod_shift, XKB_STATE_MODS_DEPRESSED);
|
wayl->kbd.xkb_state, wayl->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED);
|
||||||
term->wl.kbd.alt = xkb_state_mod_index_is_active(
|
wayl->kbd.alt = xkb_state_mod_index_is_active(
|
||||||
term->wl.kbd.xkb_state, term->wl.kbd.mod_alt, XKB_STATE_MODS_DEPRESSED);
|
wayl->kbd.xkb_state, wayl->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED);
|
||||||
term->wl.kbd.ctrl = xkb_state_mod_index_is_active(
|
wayl->kbd.ctrl = xkb_state_mod_index_is_active(
|
||||||
term->wl.kbd.xkb_state, term->wl.kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED);
|
wayl->kbd.xkb_state, wayl->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED);
|
||||||
term->wl.kbd.meta = xkb_state_mod_index_is_active(
|
wayl->kbd.meta = xkb_state_mod_index_is_active(
|
||||||
term->wl.kbd.xkb_state, term->wl.kbd.mod_meta, XKB_STATE_MODS_DEPRESSED);
|
wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
int32_t rate, int32_t delay)
|
int32_t rate, int32_t delay)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
LOG_DBG("keyboard repeat: rate=%d, delay=%d", rate, delay);
|
LOG_DBG("keyboard repeat: rate=%d, delay=%d", rate, delay);
|
||||||
term->wl.kbd.repeat.rate = rate;
|
wayl->kbd.repeat.rate = rate;
|
||||||
term->wl.kbd.repeat.delay = delay;
|
wayl->kbd.repeat.delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct wl_keyboard_listener keyboard_listener = {
|
const struct wl_keyboard_listener keyboard_listener = {
|
||||||
|
|
@ -373,7 +378,7 @@ const struct wl_keyboard_listener keyboard_listener = {
|
||||||
void
|
void
|
||||||
input_repeat(struct terminal *term, uint32_t key)
|
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
|
static void
|
||||||
|
|
@ -381,13 +386,16 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t serial, struct wl_surface *surface,
|
uint32_t serial, struct wl_surface *surface,
|
||||||
wl_fixed_t surface_x, wl_fixed_t surface_y)
|
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 x = wl_fixed_to_int(surface_x) * term->scale;
|
||||||
int y = wl_fixed_to_int(surface_y) * term->scale;
|
int y = wl_fixed_to_int(surface_y) * term->scale;
|
||||||
|
|
||||||
term->mouse.col = x / term->cell_width;
|
wayl->mouse.col = x / term->cell_width;
|
||||||
term->mouse.row = y / term->cell_height;
|
wayl->mouse.row = y / term->cell_height;
|
||||||
|
|
||||||
render_update_cursor_surface(term);
|
render_update_cursor_surface(term);
|
||||||
}
|
}
|
||||||
|
|
@ -396,13 +404,17 @@ static void
|
||||||
wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t serial, struct wl_surface *surface)
|
uint32_t serial, struct wl_surface *surface)
|
||||||
{
|
{
|
||||||
|
struct wayland *wayl = data;
|
||||||
|
wayl->moused = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
|
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 x = wl_fixed_to_int(surface_x) * term->scale;
|
||||||
int y = wl_fixed_to_int(surface_y) * 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)
|
if (col < 0 || row < 0 || col >= term->cols || row >= term->rows)
|
||||||
return;
|
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;
|
bool update_selection_early = term->selection.end.row == -1;
|
||||||
|
|
||||||
if (update_selection && update_selection_early)
|
if (update_selection && update_selection_early)
|
||||||
selection_update(term, col, row);
|
selection_update(term, col, row);
|
||||||
|
|
||||||
if (col == term->mouse.col && row == term->mouse.row)
|
if (col == wayl->mouse.col && row == wayl->mouse.row)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
term->mouse.col = col;
|
wayl->mouse.col = col;
|
||||||
term->mouse.row = row;
|
wayl->mouse.row = row;
|
||||||
|
|
||||||
if (update_selection && !update_selection_early)
|
if (update_selection && !update_selection_early)
|
||||||
selection_update(term, col, row);
|
selection_update(term, col, row);
|
||||||
|
|
||||||
term_mouse_motion(
|
term_mouse_motion(
|
||||||
term, term->mouse.button, term->mouse.row, term->mouse.col,
|
term, wayl->mouse.button, wayl->mouse.row, wayl->mouse.col,
|
||||||
term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl);
|
wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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);
|
search_cancel(term);
|
||||||
|
|
||||||
|
|
@ -448,43 +462,43 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
/* Time since last click */
|
/* Time since last click */
|
||||||
struct timeval now, since_last;
|
struct timeval now, since_last;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
timersub(&now, &term->mouse.last_time, &since_last);
|
timersub(&now, &wayl->mouse.last_time, &since_last);
|
||||||
|
|
||||||
/* Double- or triple click? */
|
/* Double- or triple click? */
|
||||||
if (button == term->mouse.last_button &&
|
if (button == wayl->mouse.last_button &&
|
||||||
since_last.tv_sec == 0 &&
|
since_last.tv_sec == 0 &&
|
||||||
since_last.tv_usec <= 300 * 1000)
|
since_last.tv_usec <= 300 * 1000)
|
||||||
{
|
{
|
||||||
term->mouse.count++;
|
wayl->mouse.count++;
|
||||||
} else
|
} else
|
||||||
term->mouse.count = 1;
|
wayl->mouse.count = 1;
|
||||||
|
|
||||||
if (button == BTN_LEFT) {
|
if (button == BTN_LEFT) {
|
||||||
switch (term->mouse.count) {
|
switch (wayl->mouse.count) {
|
||||||
case 1:
|
case 1:
|
||||||
selection_start(term, term->mouse.col, term->mouse.row);
|
selection_start(term, wayl->mouse.col, wayl->mouse.row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
selection_mark_word(term, term->mouse.col, term->mouse.row,
|
selection_mark_word(term, wayl->mouse.col, wayl->mouse.row,
|
||||||
term->wl.kbd.ctrl, serial);
|
wayl->kbd.ctrl, serial);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
selection_mark_row(term, term->mouse.row, serial);
|
selection_mark_row(term, wayl->mouse.row, serial);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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_from_primary(term);
|
||||||
selection_cancel(term);
|
selection_cancel(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
term->mouse.button = button; /* For motion events */
|
wayl->mouse.button = button; /* For motion events */
|
||||||
term->mouse.last_button = button;
|
wayl->mouse.last_button = button;
|
||||||
term->mouse.last_time = now;
|
wayl->mouse.last_time = now;
|
||||||
term_mouse_down(term, button, term->mouse.row, term->mouse.col,
|
term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col,
|
||||||
term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl);
|
wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -494,16 +508,19 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
else
|
else
|
||||||
selection_finalize(term, serial);
|
selection_finalize(term, serial);
|
||||||
|
|
||||||
term->mouse.button = 0; /* For motion events */
|
wayl->mouse.button = 0; /* For motion events */
|
||||||
term_mouse_up(term, button, term->mouse.row, term->mouse.col,
|
term_mouse_up(term, button, wayl->mouse.row, wayl->mouse.col,
|
||||||
term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl);
|
wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
int button = amount < 0 ? BTN_BACK : BTN_FORWARD;
|
||||||
|
|
||||||
void (*scrollback)(struct terminal *term, int rows)
|
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(
|
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++)
|
for (int i = 0; i < amount; i++)
|
||||||
keyboard_key(term, NULL, term->input_serial, 0, key - 8, XKB_KEY_DOWN);
|
keyboard_key(term, NULL, wayl->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_UP);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < amount; i++)
|
for (int i = 0; i < amount; i++)
|
||||||
term_mouse_down(term, button, term->mouse.row, term->mouse.col,
|
term_mouse_down(term, button, wayl->mouse.row, wayl->mouse.col,
|
||||||
term->wl.kbd.shift, term->wl.kbd.alt, term->wl.kbd.ctrl);
|
wayl->kbd.shift, wayl->kbd.alt, wayl->kbd.ctrl);
|
||||||
|
|
||||||
scrollback(term, amount);
|
scrollback(term, amount);
|
||||||
}
|
}
|
||||||
|
|
@ -541,11 +558,12 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
if (term->mouse.have_discrete)
|
|
||||||
|
if (wayl->mouse.have_discrete)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mouse_scroll(term, wl_fixed_to_int(value));
|
mouse_scroll(wayl, wl_fixed_to_int(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -555,16 +573,16 @@ wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
term->mouse.have_discrete = true;
|
wayl->mouse.have_discrete = true;
|
||||||
mouse_scroll(term, discrete);
|
mouse_scroll(wayl, discrete);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
|
wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
term->mouse.have_discrete = false;
|
wayl->mouse.have_discrete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
138
main.c
138
main.c
|
|
@ -49,9 +49,9 @@
|
||||||
static void
|
static void
|
||||||
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
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)
|
if (format == WL_SHM_FORMAT_ARGB8888)
|
||||||
term->wl.have_argb8888 = true;
|
wayl->have_argb8888 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_shm_listener shm_listener = {
|
static const struct wl_shm_listener shm_listener = {
|
||||||
|
|
@ -73,26 +73,26 @@ static void
|
||||||
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
||||||
enum wl_seat_capability caps)
|
enum wl_seat_capability caps)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
|
|
||||||
if (term->wl.keyboard != NULL) {
|
if (wayl->keyboard != NULL) {
|
||||||
wl_keyboard_release(term->wl.keyboard);
|
wl_keyboard_release(wayl->keyboard);
|
||||||
term->wl.keyboard = NULL;
|
wayl->keyboard = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (term->wl.pointer.pointer != NULL) {
|
if (wayl->pointer.pointer != NULL) {
|
||||||
wl_pointer_release(term->wl.pointer.pointer);
|
wl_pointer_release(wayl->pointer.pointer);
|
||||||
term->wl.pointer.pointer = NULL;
|
wayl->pointer.pointer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
|
if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||||
term->wl.keyboard = wl_seat_get_keyboard(wl_seat);
|
wayl->keyboard = wl_seat_get_keyboard(wl_seat);
|
||||||
wl_keyboard_add_listener(term->wl.keyboard, &keyboard_listener, term);
|
wl_keyboard_add_listener(wayl->keyboard, &keyboard_listener, wayl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps & WL_SEAT_CAPABILITY_POINTER) {
|
if (caps & WL_SEAT_CAPABILITY_POINTER) {
|
||||||
term->wl.pointer.pointer = wl_seat_get_pointer(wl_seat);
|
wayl->pointer.pointer = wl_seat_get_pointer(wl_seat);
|
||||||
wl_pointer_add_listener(term->wl.pointer.pointer, &pointer_listener, term);
|
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)
|
output_scale(void *data, struct wl_output *wl_output, int32_t factor)
|
||||||
{
|
{
|
||||||
struct monitor *mon = data;
|
struct monitor *mon = data;
|
||||||
|
struct terminal *term = mon->wayl->term;
|
||||||
|
|
||||||
mon->scale = factor;
|
mon->scale = factor;
|
||||||
|
|
||||||
render_resize(mon->term, mon->term->width / mon->term->scale, mon->term->height / mon->term->scale);
|
render_resize(term, term->width / term->scale, term->height / term->scale);
|
||||||
render_reload_cursor_theme(mon->term);
|
render_reload_cursor_theme(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
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)
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
{
|
{
|
||||||
LOG_DBG("global: %s, version=%u", interface, 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) {
|
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||||
term->wl.compositor = wl_registry_bind(
|
wayl->compositor = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_compositor_interface, 4);
|
wayl->registry, name, &wl_compositor_interface, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
|
else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
|
||||||
term->wl.sub_compositor = wl_registry_bind(
|
wayl->sub_compositor = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_subcompositor_interface, 1);
|
wayl->registry, name, &wl_subcompositor_interface, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, wl_shm_interface.name) == 0) {
|
else if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||||
term->wl.shm = wl_registry_bind(
|
wayl->shm = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_shm_interface, 1);
|
wayl->registry, name, &wl_shm_interface, 1);
|
||||||
wl_shm_add_listener(term->wl.shm, &shm_listener, term);
|
wl_shm_add_listener(wayl->shm, &shm_listener, wayl);
|
||||||
wl_display_roundtrip(term->wl.display);
|
wl_display_roundtrip(wayl->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||||
term->window.shell = wl_registry_bind(
|
wayl->shell = wl_registry_bind(
|
||||||
term->wl.registry, name, &xdg_wm_base_interface, 1);
|
wayl->registry, name, &xdg_wm_base_interface, 1);
|
||||||
xdg_wm_base_add_listener(term->window.shell, &xdg_wm_base_listener, term);
|
xdg_wm_base_add_listener(wayl->shell, &xdg_wm_base_listener, wayl);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0)
|
else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0)
|
||||||
term->window.xdg_decoration_manager = wl_registry_bind(
|
wayl->xdg_decoration_manager = wl_registry_bind(
|
||||||
term->wl.registry, name, &zxdg_decoration_manager_v1_interface, 1);
|
wayl->registry, name, &zxdg_decoration_manager_v1_interface, 1);
|
||||||
|
|
||||||
else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
term->wl.seat = wl_registry_bind(
|
wayl->seat = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_seat_interface, 5);
|
wayl->registry, name, &wl_seat_interface, 5);
|
||||||
wl_seat_add_listener(term->wl.seat, &seat_listener, term);
|
wl_seat_add_listener(wayl->seat, &seat_listener, wayl);
|
||||||
wl_display_roundtrip(term->wl.display);
|
wl_display_roundtrip(wayl->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
||||||
term->wl.xdg_output_manager = wl_registry_bind(
|
wayl->xdg_output_manager = wl_registry_bind(
|
||||||
term->wl.registry, name, &zxdg_output_manager_v1_interface, min(version, 2));
|
wayl->registry, name, &zxdg_output_manager_v1_interface, min(version, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, wl_output_interface.name) == 0) {
|
else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
struct wl_output *output = wl_registry_bind(
|
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(
|
tll_push_back(
|
||||||
term->wl.monitors, ((struct monitor){
|
wayl->monitors, ((struct monitor){.wayl = wayl, .output = output}));
|
||||||
.term = term, .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);
|
wl_output_add_listener(output, &output_listener, mon);
|
||||||
|
|
||||||
mon->xdg = zxdg_output_manager_v1_get_xdg_output(
|
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);
|
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) {
|
else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
|
||||||
term->wl.data_device_manager = wl_registry_bind(
|
wayl->data_device_manager = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_data_device_manager_interface, 1);
|
wayl->registry, name, &wl_data_device_manager_interface, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
|
else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
|
||||||
term->wl.primary_selection_device_manager = wl_registry_bind(
|
wayl->primary_selection_device_manager = wl_registry_bind(
|
||||||
term->wl.registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
|
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,
|
surface_enter(void *data, struct wl_surface *wl_surface,
|
||||||
struct wl_output *wl_output)
|
struct wl_output *wl_output)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
tll_foreach(term->wl.monitors, it) {
|
struct terminal *term = wayl_terminal_from_surface(wayl, wl_surface);
|
||||||
|
|
||||||
|
tll_foreach(wayl->monitors, it) {
|
||||||
if (it->item.output == wl_output) {
|
if (it->item.output == wl_output) {
|
||||||
LOG_DBG("mapped on %s", it->item.name);
|
LOG_DBG("mapped on %s", it->item.name);
|
||||||
tll_push_back(term->window.on_outputs, &it->item);
|
tll_push_back(term->window.on_outputs, &it->item);
|
||||||
|
|
@ -293,7 +296,9 @@ static void
|
||||||
surface_leave(void *data, struct wl_surface *wl_surface,
|
surface_leave(void *data, struct wl_surface *wl_surface,
|
||||||
struct wl_output *wl_output)
|
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) {
|
tll_foreach(term->window.on_outputs, it) {
|
||||||
if (it->item->output != wl_output)
|
if (it->item->output != wl_output)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -324,17 +329,20 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
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);
|
render_resize(term, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
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");
|
LOG_DBG("xdg-toplevel: close");
|
||||||
|
|
||||||
term->quit = true;
|
term->quit = true;
|
||||||
wl_display_roundtrip(term->wl.display);
|
wl_display_roundtrip(wayl->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||||
|
|
@ -393,15 +401,15 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
static bool
|
static bool
|
||||||
fdm_wayl(struct fdm *fdm, int fd, int events, void *data)
|
fdm_wayl(struct fdm *fdm, int fd, int events, void *data)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
int event_count = wl_display_dispatch(term->wl.display);
|
int event_count = wl_display_dispatch(wayl->display);
|
||||||
|
|
||||||
if (events & EPOLLHUP) {
|
if (events & EPOLLHUP) {
|
||||||
LOG_ERR("disconnected from Wayland");
|
LOG_ERR("disconnected from Wayland");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return event_count != -1 && !term->quit;
|
return event_count != -1 && !wayl->term->quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -900,7 +908,7 @@ main(int argc, char *const *argv)
|
||||||
goto out;
|
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);
|
wl_display_roundtrip(term.wl.display);
|
||||||
|
|
||||||
if (term.wl.compositor == NULL) {
|
if (term.wl.compositor == NULL) {
|
||||||
|
|
@ -911,7 +919,7 @@ main(int argc, char *const *argv)
|
||||||
LOG_ERR("no shared memory buffers interface");
|
LOG_ERR("no shared memory buffers interface");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (term.window.shell == NULL) {
|
if (term.wl.shell == NULL) {
|
||||||
LOG_ERR("no XDG shell interface");
|
LOG_ERR("no XDG shell interface");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -940,14 +948,14 @@ main(int argc, char *const *argv)
|
||||||
/* Clipboard */
|
/* Clipboard */
|
||||||
term.wl.data_device = wl_data_device_manager_get_data_device(
|
term.wl.data_device = wl_data_device_manager_get_data_device(
|
||||||
term.wl.data_device_manager, term.wl.seat);
|
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 */
|
/* Primary selection */
|
||||||
if (term.wl.primary_selection_device_manager != NULL) {
|
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 = zwp_primary_selection_device_manager_v1_get_device(
|
||||||
term.wl.primary_selection_device_manager, term.wl.seat);
|
term.wl.primary_selection_device_manager, term.wl.seat);
|
||||||
zwp_primary_selection_device_v1_add_listener(
|
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 */
|
/* Cursor */
|
||||||
|
|
@ -981,24 +989,24 @@ main(int argc, char *const *argv)
|
||||||
goto out;
|
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);
|
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);
|
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);
|
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");
|
xdg_toplevel_set_app_id(term.window.xdg_toplevel, "foot");
|
||||||
term_set_window_title(&term, "foot");
|
term_set_window_title(&term, "foot");
|
||||||
|
|
||||||
/* Request server-side decorations */
|
/* Request server-side decorations */
|
||||||
term.window.xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
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(
|
zxdg_toplevel_decoration_v1_set_mode(
|
||||||
term.window.xdg_toplevel_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
term.window.xdg_toplevel_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
zxdg_toplevel_decoration_v1_add_listener(
|
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 */
|
/* Scrollback search box */
|
||||||
term.window.search_surface = wl_compositor_create_surface(term.wl.compositor);
|
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)
|
if ((fdm = fdm_init()) == NULL)
|
||||||
goto out;
|
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.ptmx, EPOLLIN, &fdm_ptmx, &term);
|
||||||
fdm_add(fdm, term.wl.kbd.repeat.fd, EPOLLIN, &fdm_repeat, &term);
|
fdm_add(fdm, term.wl.kbd.repeat.fd, EPOLLIN, &fdm_repeat, &term);
|
||||||
fdm_add(fdm, term.flash.fd, EPOLLIN, &fdm_flash, &term);
|
fdm_add(fdm, term.flash.fd, EPOLLIN, &fdm_flash, &term);
|
||||||
|
|
|
||||||
6
osc.c
6
osc.c
|
|
@ -30,14 +30,14 @@ osc_to_clipboard(struct terminal *term, const char *target,
|
||||||
switch (*t) {
|
switch (*t) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
char *copy = strdup(decoded);
|
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);
|
free(copy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p': {
|
case 'p': {
|
||||||
char *copy = strdup(decoded);
|
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);
|
free(copy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,7 @@ osc_from_clipboard(struct terminal *term, const char *source)
|
||||||
|
|
||||||
switch (src) {
|
switch (src) {
|
||||||
case 'c':
|
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;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
|
|
|
||||||
2
search.c
2
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 */
|
/* "Commit" search - copy selection to primary and cancel search */
|
||||||
else if (mods == 0 && sym == XKB_KEY_Return) {
|
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);
|
search_cancel_keep_selection(term);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -742,8 +742,8 @@ selection(void *data, struct wl_data_device *wl_data_device,
|
||||||
{
|
{
|
||||||
/* Selection offer from other client */
|
/* Selection offer from other client */
|
||||||
|
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
struct wl_clipboard *clipboard = &term->wl.clipboard;
|
struct wl_clipboard *clipboard = &wayl->clipboard;
|
||||||
|
|
||||||
if (clipboard->data_offer != NULL)
|
if (clipboard->data_offer != NULL)
|
||||||
wl_data_offer_destroy(clipboard->data_offer);
|
wl_data_offer_destroy(clipboard->data_offer);
|
||||||
|
|
@ -791,8 +791,8 @@ primary_selection(void *data,
|
||||||
{
|
{
|
||||||
/* Selection offer from other client, for primary */
|
/* Selection offer from other client, for primary */
|
||||||
|
|
||||||
struct terminal *term = data;
|
struct wayland *wayl = data;
|
||||||
struct wl_primary *primary = &term->wl.primary;
|
struct wl_primary *primary = &wayl->primary;
|
||||||
|
|
||||||
if (primary->data_offer != NULL)
|
if (primary->data_offer != NULL)
|
||||||
zwp_primary_selection_offer_v1_destroy(primary->data_offer);
|
zwp_primary_selection_offer_v1_destroy(primary->data_offer);
|
||||||
|
|
|
||||||
14
terminal.h
14
terminal.h
|
|
@ -200,19 +200,6 @@ struct terminal {
|
||||||
uint32_t default_table[256];
|
uint32_t default_table[256];
|
||||||
} colors;
|
} 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 cursor;
|
||||||
struct coord saved_cursor;
|
struct coord saved_cursor;
|
||||||
struct coord alt_saved_cursor;
|
struct coord alt_saved_cursor;
|
||||||
|
|
@ -228,7 +215,6 @@ struct terminal {
|
||||||
uint32_t cursor;
|
uint32_t cursor;
|
||||||
} cursor_color;
|
} cursor_color;
|
||||||
|
|
||||||
uint32_t input_serial;
|
|
||||||
struct {
|
struct {
|
||||||
struct coord start;
|
struct coord start;
|
||||||
struct coord end;
|
struct coord end;
|
||||||
|
|
|
||||||
25
wayland.c
25
wayland.c
|
|
@ -13,6 +13,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include "tllist.h"
|
#include "tllist.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
wayl_init(struct wayland *wayl)
|
wayl_init(struct wayland *wayl)
|
||||||
|
|
@ -33,6 +34,11 @@ wayl_destroy(struct wayland *wayl)
|
||||||
|
|
||||||
if (wayl->xdg_output_manager != NULL)
|
if (wayl->xdg_output_manager != NULL)
|
||||||
zxdg_output_manager_v1_destroy(wayl->xdg_output_manager);
|
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)
|
if (wayl->kbd.xkb_compose_state != NULL)
|
||||||
xkb_compose_state_unref(wayl->kbd.xkb_compose_state);
|
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);
|
wl_callback_destroy(win->frame_callback);
|
||||||
if (win->xdg_toplevel_decoration != NULL)
|
if (win->xdg_toplevel_decoration != NULL)
|
||||||
zxdg_toplevel_decoration_v1_destroy(win->xdg_toplevel_decoration);
|
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)
|
if (win->xdg_toplevel != NULL)
|
||||||
xdg_toplevel_destroy(win->xdg_toplevel);
|
xdg_toplevel_destroy(win->xdg_toplevel);
|
||||||
if (win->xdg_surface != NULL)
|
if (win->xdg_surface != NULL)
|
||||||
xdg_surface_destroy(win->xdg_surface);
|
xdg_surface_destroy(win->xdg_surface);
|
||||||
if (win->shell != NULL)
|
|
||||||
xdg_wm_base_destroy(win->shell);
|
|
||||||
if (win->surface != NULL)
|
if (win->surface != NULL)
|
||||||
wl_surface_destroy(win->surface);
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
31
wayland.h
31
wayland.h
|
|
@ -10,7 +10,8 @@
|
||||||
#include "tllist.h"
|
#include "tllist.h"
|
||||||
|
|
||||||
struct monitor {
|
struct monitor {
|
||||||
struct terminal *term;
|
//struct terminal *term;
|
||||||
|
struct wayland *wayl;
|
||||||
struct wl_output *output;
|
struct wl_output *output;
|
||||||
struct zxdg_output_v1 *xdg;
|
struct zxdg_output_v1 *xdg;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
@ -71,11 +72,9 @@ struct wl_primary {
|
||||||
|
|
||||||
struct wl_window {
|
struct wl_window {
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct xdg_wm_base *shell;
|
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
|
|
||||||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager;
|
|
||||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
||||||
|
|
||||||
/* Scrollback search */
|
/* Scrollback search */
|
||||||
|
|
@ -99,10 +98,14 @@ struct wayland {
|
||||||
struct wl_keyboard *keyboard;
|
struct wl_keyboard *keyboard;
|
||||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||||
|
|
||||||
|
struct xdg_wm_base *shell;
|
||||||
|
struct zxdg_decoration_manager_v1 *xdg_decoration_manager;
|
||||||
|
|
||||||
/* Keyboard */
|
/* Keyboard */
|
||||||
struct kbd kbd;
|
struct kbd kbd;
|
||||||
|
|
||||||
/* Clipboard */
|
/* Clipboard */
|
||||||
|
uint32_t input_serial;
|
||||||
struct wl_data_device_manager *data_device_manager;
|
struct wl_data_device_manager *data_device_manager;
|
||||||
struct wl_data_device *data_device;
|
struct wl_data_device *data_device;
|
||||||
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
||||||
|
|
@ -123,15 +126,37 @@ struct wayland {
|
||||||
char *theme_name;
|
char *theme_name;
|
||||||
} pointer;
|
} 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;
|
bool have_argb8888;
|
||||||
tll(struct monitor) monitors; /* All available outputs */
|
tll(struct monitor) monitors; /* All available outputs */
|
||||||
|
|
||||||
/* TODO: turn into a list to support multiple windows */
|
/* TODO: turn into a list to support multiple windows */
|
||||||
struct terminal *term;
|
struct terminal *term;
|
||||||
|
struct terminal *focused;
|
||||||
|
struct terminal *moused;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: return allocated pointer */
|
/* TODO: return allocated pointer */
|
||||||
void wayl_init(struct wayland *wayl);
|
void wayl_init(struct wayland *wayl);
|
||||||
void wayl_destroy(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);
|
void wayl_win_destroy(struct wl_window *win);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue