diff --git a/include/input/cursor.h b/include/input/cursor.h index c126312..8888dd7 100644 --- a/include/input/cursor.h +++ b/include/input/cursor.h @@ -43,6 +43,7 @@ struct kiwmi_cursor { struct { struct wl_signal button_down; struct wl_signal button_up; + struct wl_signal destroy; struct wl_signal motion; struct wl_signal scroll; } events; diff --git a/include/input/keyboard.h b/include/input/keyboard.h index cc45206..1393fe0 100644 --- a/include/input/keyboard.h +++ b/include/input/keyboard.h @@ -40,5 +40,6 @@ struct kiwmi_keyboard_key_event { struct kiwmi_keyboard * keyboard_create(struct kiwmi_server *server, struct wlr_input_device *device); +void keyboard_destroy(struct kiwmi_keyboard *keyboard); #endif /* KIWMI_INPUT_KEYBOARD_H */ diff --git a/include/server.h b/include/server.h index e721ded..cbc59d2 100644 --- a/include/server.h +++ b/include/server.h @@ -22,6 +22,10 @@ struct kiwmi_server { struct kiwmi_lua *lua; struct kiwmi_desktop desktop; struct kiwmi_input input; + + struct { + struct wl_signal destroy; + } events; }; bool server_init(struct kiwmi_server *server, char *config_path); diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index 5cbd97b..35f5ecd 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -85,6 +85,7 @@ void desktop_fini(struct kiwmi_desktop *desktop) { wlr_output_layout_destroy(desktop->output_layout); + desktop->output_layout = NULL; } struct kiwmi_output * diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index 6a81508..986cbe2 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -264,14 +264,20 @@ output_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_output *output = wl_container_of(listener, output, destroy); - wlr_output_layout_remove( - output->desktop->output_layout, output->wlr_output); + if (output->desktop->output_layout) { + wlr_output_layout_remove( + output->desktop->output_layout, output->wlr_output); + } wl_signal_emit(&output->events.destroy, output); wl_list_remove(&output->link); wl_list_remove(&output->frame.link); + wl_list_remove(&output->commit.link); wl_list_remove(&output->destroy.link); + wl_list_remove(&output->mode.link); + + wl_list_remove(&output->events.destroy.listener_list); free(output); } diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 3d79420..d7f50f6 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -239,6 +239,10 @@ xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) view_child_destroy(child); } + if (view->decoration) { + view->decoration->view = NULL; + } + wl_list_remove(&view->link); wl_list_remove(&view->children); wl_list_remove(&view->map.link); @@ -250,6 +254,8 @@ xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) wl_list_remove(&view->request_move.link); wl_list_remove(&view->request_resize.link); + wl_list_remove(&view->events.unmap.listener_list); + free(view); } @@ -509,7 +515,9 @@ xdg_decoration_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_xdg_decoration *decoration = wl_container_of(listener, decoration, destroy); - decoration->view->decoration = NULL; + if (decoration->view) { + decoration->view->decoration = NULL; + } wl_list_remove(&decoration->destroy.link); wl_list_remove(&decoration->request_mode.link); diff --git a/kiwmi/input/cursor.c b/kiwmi/input/cursor.c index b86fc30..33792ba 100644 --- a/kiwmi/input/cursor.c +++ b/kiwmi/input/cursor.c @@ -254,6 +254,7 @@ cursor_create( wl_signal_init(&cursor->events.button_down); wl_signal_init(&cursor->events.button_up); + wl_signal_init(&cursor->events.destroy); wl_signal_init(&cursor->events.motion); wl_signal_init(&cursor->events.scroll); @@ -263,14 +264,12 @@ cursor_create( void cursor_destroy(struct kiwmi_cursor *cursor) { + wl_signal_emit(&cursor->events.destroy, cursor); + wlr_cursor_destroy(cursor->cursor); wlr_xcursor_manager_destroy(cursor->xcursor_manager); - wl_list_remove(&cursor->cursor_motion.link); - wl_list_remove(&cursor->cursor_motion_absolute.link); - wl_list_remove(&cursor->cursor_button.link); - wl_list_remove(&cursor->cursor_axis.link); - wl_list_remove(&cursor->cursor_frame.link); + // The wlr_cursor is already destroyed, don't unregister listeners free(cursor); } diff --git a/kiwmi/input/input.c b/kiwmi/input/input.c index 6f684ec..d49ff9f 100644 --- a/kiwmi/input/input.c +++ b/kiwmi/input/input.c @@ -101,7 +101,7 @@ input_fini(struct kiwmi_input *input) struct kiwmi_keyboard *keyboard; struct kiwmi_keyboard *tmp; wl_list_for_each_safe (keyboard, tmp, &input->keyboards, link) { - free(keyboard); + keyboard_destroy(keyboard); } seat_destroy(input->seat); diff --git a/kiwmi/input/keyboard.c b/kiwmi/input/keyboard.c index fd6613d..a9d7637 100644 --- a/kiwmi/input/keyboard.c +++ b/kiwmi/input/keyboard.c @@ -116,14 +116,7 @@ keyboard_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_keyboard *keyboard = wl_container_of(listener, keyboard, device_destroy); - wl_list_remove(&keyboard->link); - wl_list_remove(&keyboard->modifiers.link); - wl_list_remove(&keyboard->key.link); - wl_list_remove(&keyboard->device_destroy.link); - - wl_signal_emit(&keyboard->events.destroy, keyboard); - - free(keyboard); + keyboard_destroy(keyboard); } struct kiwmi_keyboard * @@ -167,3 +160,19 @@ keyboard_create(struct kiwmi_server *server, struct wlr_input_device *device) return keyboard; } + +void +keyboard_destroy(struct kiwmi_keyboard *keyboard) +{ + wl_list_remove(&keyboard->modifiers.link); + wl_list_remove(&keyboard->key.link); + wl_list_remove(&keyboard->device_destroy.link); + + wl_signal_emit(&keyboard->events.destroy, keyboard); + + wl_list_remove(&keyboard->link); + + wl_list_remove(&keyboard->events.destroy.listener_list); + + free(keyboard); +} diff --git a/kiwmi/luak/kiwmi_cursor.c b/kiwmi/luak/kiwmi_cursor.c index 97eb159..986e6ae 100644 --- a/kiwmi/luak/kiwmi_cursor.c +++ b/kiwmi/luak/kiwmi_cursor.c @@ -309,7 +309,8 @@ luaK_kiwmi_cursor_new(lua_State *L) struct kiwmi_lua *lua = lua_touserdata(L, 1); struct kiwmi_cursor *cursor = lua_touserdata(L, 2); - struct kiwmi_object *obj = luaK_get_kiwmi_object(lua, cursor, NULL); + struct kiwmi_object *obj = + luaK_get_kiwmi_object(lua, cursor, &cursor->events.destroy); struct kiwmi_object **cursor_ud = lua_newuserdata(L, sizeof(*cursor_ud)); luaL_getmetatable(L, "kiwmi_cursor"); diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index 6c8e8f4..6ba118b 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -574,7 +574,8 @@ luaK_kiwmi_server_new(lua_State *L) struct kiwmi_lua *lua = lua_touserdata(L, 1); struct kiwmi_server *server = lua_touserdata(L, 2); - struct kiwmi_object *obj = luaK_get_kiwmi_object(lua, server, NULL); + struct kiwmi_object *obj = + luaK_get_kiwmi_object(lua, server, &server->events.destroy); struct kiwmi_object **server_ud = lua_newuserdata(L, sizeof(*server_ud)); luaL_getmetatable(L, "kiwmi_server"); diff --git a/kiwmi/luak/luak.c b/kiwmi/luak/luak.c index 3019f61..8a094e9 100644 --- a/kiwmi/luak/luak.c +++ b/kiwmi/luak/luak.c @@ -39,6 +39,15 @@ luaK_toudata(lua_State *L, int ud, const char *tname) return NULL; } +static void +kiwmi_object_destroy(struct kiwmi_object *obj) +{ + wl_list_remove(&obj->destroy.link); + wl_list_remove(&obj->events.destroy.listener_list); + + free(obj); +} + int luaK_kiwmi_object_gc(lua_State *L) { @@ -47,7 +56,7 @@ luaK_kiwmi_object_gc(lua_State *L) --obj->refcount; if (obj->refcount == 0 && wl_list_empty(&obj->callbacks)) { - free(obj); + kiwmi_object_destroy(obj); } return 0; @@ -71,8 +80,6 @@ kiwmi_object_destroy_notify(struct wl_listener *listener, void *data) free(lc); } - wl_list_remove(&obj->destroy.link); - lua_State *L = obj->lua->L; lua_rawgeti(L, LUA_REGISTRYINDEX, obj->lua->objects); @@ -84,7 +91,7 @@ kiwmi_object_destroy_notify(struct wl_listener *listener, void *data) obj->valid = false; if (obj->refcount == 0) { - free(obj); + kiwmi_object_destroy(obj); } } @@ -123,10 +130,12 @@ luaK_get_kiwmi_object( if (destroy) { obj->destroy.notify = kiwmi_object_destroy_notify; wl_signal_add(destroy, &obj->destroy); - - wl_signal_init(&obj->events.destroy); + } else { + wl_list_init(&obj->destroy.link); } + wl_signal_init(&obj->events.destroy); + wl_list_init(&obj->callbacks); lua_rawgeti(L, LUA_REGISTRYINDEX, lua->objects); diff --git a/kiwmi/server.c b/kiwmi/server.c index 7cc7d2e..5262276 100644 --- a/kiwmi/server.c +++ b/kiwmi/server.c @@ -46,6 +46,8 @@ server_init(struct kiwmi_server *server, char *config_path) struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); wlr_renderer_init_wl_display(renderer, server->wl_display); + wl_signal_init(&server->events.destroy); + if (!desktop_init(&server->desktop, renderer)) { wlr_log(WLR_ERROR, "Failed to initialize desktop"); wl_display_destroy(server->wl_display); @@ -132,12 +134,15 @@ server_fini(struct kiwmi_server *server) { wlr_log(WLR_DEBUG, "Shutting down Wayland server"); + wl_signal_emit(&server->events.destroy, server); + wl_display_destroy_clients(server->wl_display); - wl_display_destroy(server->wl_display); desktop_fini(&server->desktop); input_fini(&server->input); + wl_display_destroy(server->wl_display); + luaK_destroy(server->lua); free(server->config_path);