diff --git a/src/action.h b/src/action.h index ea56698..721b436 100644 --- a/src/action.h +++ b/src/action.h @@ -5,3 +5,4 @@ void spawn(const user_action_arg_t *arg); void quit(const user_action_arg_t *arg); void select_tag(const user_action_arg_t *arg); +void kill_client(const user_action_arg_t *arg); diff --git a/src/config.h b/src/config.h index b9df131..469a127 100644 --- a/src/config.h +++ b/src/config.h @@ -90,6 +90,7 @@ const keybinding_t keys[] = { {SUPER, XK_p, spawn, {.ptr = launcher}}, {SUPER | SHIFT, XK_q, quit, {.b = false}}, {SUPER | CTRL, XK_r, quit, {.b = true}}, + {SUPER | SHIFT, XK_c, kill_client, {0}}, {SUPER, XK_1, select_tag, {.ui = 0}}, {SUPER, XK_2, select_tag, {.ui = 1}}, {SUPER, XK_3, select_tag, {.ui = 2}}, diff --git a/src/include/xcb.h b/src/include/xcb.h index 03a4b44..1375f71 100644 --- a/src/include/xcb.h +++ b/src/include/xcb.h @@ -58,6 +58,10 @@ void raise_window(xcb_window_t window); * @brief 在堆叠顺序中将 window 置于 sibling 之下 */ void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling); +/** + * @brief 关闭窗口并清理资源 + */ +void kill_window(xcb_window_t window); typedef struct bar_cairo_params_t { xcb_connection_t *conn; diff --git a/src/main.c b/src/main.c index 6e6b1b3..eda4be5 100644 --- a/src/main.c +++ b/src/main.c @@ -104,6 +104,15 @@ void select_tag(const user_action_arg_t *arg) { arrange(current_monitor); } +void kill_client(const user_action_arg_t *arg) { + client_t *client = current_monitor->selected_client; + if (!client) return; + + if (!send_event(client->window, get_xcb_atom(atom_wm_delete))) { + kill_window(client->window); + } +} + /* 调试函数,开发完成后删除 */ static void print_monitor_list_info(monitor_t *monitor_list) { logger("========================= monitor info =========================\n"); diff --git a/src/xcb/window.c b/src/xcb/window.c index 57e209a..87b9131 100644 --- a/src/xcb/window.c +++ b/src/xcb/window.c @@ -315,3 +315,11 @@ void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling) { }; xcb_aux_configure_window(conn, window, mask, ¶ms); } + +void kill_window(xcb_window_t window) { + xcb_grab_server(conn); + xcb_set_close_down_mode(conn, XCB_CLOSE_DOWN_DESTROY_ALL); + xcb_kill_client(conn, window); + xcb_flush(conn); + xcb_ungrab_server(conn); +}