添加关闭窗口功能
This commit is contained in:
@@ -104,3 +104,9 @@ void toggle_client_maximize(const user_action_arg_t *arg) {
|
||||
|
||||
client_set_maximize(wm.client_focused, !wm.client_focused->maximize);
|
||||
}
|
||||
|
||||
void kill_client(const user_action_arg_t *arg) {
|
||||
if (wm.client_focused) {
|
||||
client_kill(wm.client_focused);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +60,4 @@ void change_volume(const user_action_arg_t *arg);
|
||||
void toggle_client_floating(const user_action_arg_t *arg);
|
||||
void toggle_client_fullscreen(const user_action_arg_t *arg);
|
||||
void toggle_client_maximize(const user_action_arg_t *arg);
|
||||
void kill_client(const user_action_arg_t *arg);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
_XKB_RULES_NAMES
|
||||
|
||||
WM_DELETE_WINDOW
|
||||
WM_PROTOCOLS
|
||||
WM_TAKE_FOCUS
|
||||
WM_NAME
|
||||
|
||||
36
src/client.c
36
src/client.c
@@ -172,6 +172,17 @@ static void client_init_tag_by_wm_desktop(client_t *client) {
|
||||
}
|
||||
}
|
||||
|
||||
static void set_window_event_mask(xcb_window_t window, bool clean) {
|
||||
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||
uint32_t init_event_mask =
|
||||
XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
|
||||
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||
uint32_t event_mask = clean ? XCB_EVENT_MASK_NO_EVENT : init_event_mask;
|
||||
xcb_params_cw_t params = {.event_mask = event_mask};
|
||||
xcb_aux_change_window_attributes(wm.xcb_conn, window, change_mask, ¶ms);
|
||||
}
|
||||
|
||||
void client_manage(xcb_window_t window,
|
||||
xcb_get_geometry_reply_t *geometry_reply) {
|
||||
client_t *c = p_new(client_t, 1);
|
||||
@@ -184,14 +195,7 @@ void client_manage(xcb_window_t window,
|
||||
c->old_border_width = geometry_reply->border_width;
|
||||
|
||||
{
|
||||
const xcb_params_cw_t params = {
|
||||
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
|
||||
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||
};
|
||||
xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_EVENT_MASK,
|
||||
¶ms);
|
||||
set_window_event_mask(window, false);
|
||||
xcb_map_window(wm.xcb_conn, window);
|
||||
}
|
||||
client_update_names(c);
|
||||
@@ -238,6 +242,7 @@ void client_manage(xcb_window_t window,
|
||||
|
||||
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_APPEND, wm.screen->root,
|
||||
_NET_CLIENT_LIST, XCB_ATOM_WINDOW, 32, 1, &window);
|
||||
xwindow_set_state(window, XCB_ICCCM_WM_STATE_NORMAL);
|
||||
|
||||
monitor_arrange(c->monitor);
|
||||
monitor_draw_bar(c->monitor);
|
||||
@@ -477,7 +482,13 @@ static void update_client_list(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void client_unmanage(client_t *client) {
|
||||
void client_kill(client_t *client) {
|
||||
if (!xwindow_send_event(client->window, WM_DELETE_WINDOW)) {
|
||||
xwindow_kill_window(client->window);
|
||||
}
|
||||
}
|
||||
|
||||
void client_unmanage(client_t *client, bool destroyed) {
|
||||
monitor_t *m = client->monitor;
|
||||
|
||||
client_detach_list(client);
|
||||
@@ -487,6 +498,13 @@ void client_unmanage(client_t *client) {
|
||||
if (tag->mask & client->tags) client_remove_from_tag(client, tag);
|
||||
}
|
||||
|
||||
if (!destroyed) {
|
||||
set_window_event_mask(client->window, true);
|
||||
client_change_border_width(client, client->old_border_width);
|
||||
xwindow_set_state(client->window, XCB_ICCCM_WM_STATE_WITHDRAWN);
|
||||
xcb_flush(wm.xcb_conn);
|
||||
}
|
||||
|
||||
client_wipe(client);
|
||||
|
||||
update_client_list();
|
||||
|
||||
@@ -50,7 +50,7 @@ void client_set_transient_for_window(client_t *client,
|
||||
void client_set_leader_window(client_t *client, xcb_window_t leader_window);
|
||||
|
||||
void client_kill(client_t *client);
|
||||
void client_unmanage(client_t *client);
|
||||
void client_unmanage(client_t *client, bool destroyed);
|
||||
void client_apply_geometry(client_t *client, area_t geometry);
|
||||
void client_apply_workarea_geometry(client_t *client, area_t geometry);
|
||||
void client_apply_rules(client_t *client, const rule_t rules[],
|
||||
|
||||
@@ -99,6 +99,7 @@ static const keyboard_t key_list[] = {
|
||||
{modifier_super | modifier_control, XK_space, toggle_client_floating, {0}},
|
||||
{modifier_super, XK_f, toggle_client_fullscreen, {0}},
|
||||
{modifier_super, XK_m, toggle_client_maximize, {0}},
|
||||
{modifier_super | modifier_shift, XK_c, kill_client, {0}},
|
||||
|
||||
{modifier_super, XK_Up, change_volume, {.i = 1}},
|
||||
{modifier_super, XK_Down, change_volume, {.i = -1}},
|
||||
|
||||
11
src/event.c
11
src/event.c
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_event.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#include <xcb/xproto.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
@@ -201,12 +202,18 @@ static void property_notify(xcb_property_notify_event_t *ev) {
|
||||
|
||||
static void destroy_notify(xcb_destroy_notify_event_t *ev) {
|
||||
client_t *client = client_get_by_window(ev->window);
|
||||
if (client) client_unmanage(client);
|
||||
if (client) client_unmanage(client, true);
|
||||
}
|
||||
|
||||
static void unmap_notify(xcb_unmap_notify_event_t *ev) {
|
||||
client_t *client = client_get_by_window(ev->window);
|
||||
if (client) client_unmanage(client);
|
||||
if (client) {
|
||||
if (XCB_EVENT_SENT(ev)) {
|
||||
xwindow_set_state(ev->window, XCB_ICCCM_WM_STATE_WITHDRAWN);
|
||||
} else {
|
||||
client_unmanage(client, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void map_notify(xcb_map_notify_event_t *ev) {
|
||||
|
||||
11
src/wm.c
11
src/wm.c
@@ -314,6 +314,16 @@ void wm_scan_clients(void) {
|
||||
void wm_clean(void) {
|
||||
clean_status();
|
||||
text_clean_pango_layout();
|
||||
|
||||
{
|
||||
client_t *c = wm.client_stack_list;
|
||||
while (c) {
|
||||
client_t *next_client = c->stack_next;
|
||||
client_unmanage(c, false);
|
||||
c = next_client;
|
||||
}
|
||||
}
|
||||
|
||||
monitor_clean(wm.monitor_list);
|
||||
|
||||
for (int i = 0; i < countof(sources); i++) {
|
||||
@@ -321,7 +331,6 @@ void wm_clean(void) {
|
||||
if (source_id) g_source_remove(source_id);
|
||||
}
|
||||
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_CLIENT_LIST);
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_ACTIVE_WINDOW);
|
||||
xcb_delete_property(wm.xcb_conn, wm.screen->root, _NET_SUPPORTING_WM_CHECK);
|
||||
xcb_aux_sync(wm.xcb_conn);
|
||||
|
||||
@@ -228,6 +228,14 @@ bool xwindow_get_wm_desktop(xcb_window_t window, uint32_t *desktop) {
|
||||
return success;
|
||||
}
|
||||
|
||||
void xwindow_kill_window(xcb_window_t window) {
|
||||
xcb_grab_server(wm.xcb_conn);
|
||||
xcb_set_close_down_mode(wm.xcb_conn, XCB_CLOSE_DOWN_DESTROY_ALL);
|
||||
xcb_kill_client(wm.xcb_conn, window);
|
||||
xcb_flush(wm.xcb_conn);
|
||||
xcb_ungrab_server(wm.xcb_conn);
|
||||
}
|
||||
|
||||
xcb_window_t xwindow_get_transient_for(xcb_window_t window) {
|
||||
xcb_connection_t *conn = wm.xcb_conn;
|
||||
xcb_window_t t_window = XCB_WINDOW_NONE;
|
||||
@@ -250,6 +258,23 @@ int32_t xwindow_get_state(xcb_window_t window) {
|
||||
return hints.initial_state;
|
||||
}
|
||||
|
||||
void xwindow_set_state(xcb_window_t window, xcb_icccm_wm_state_t state) {
|
||||
xcb_icccm_wm_hints_t hints;
|
||||
xcb_icccm_wm_hints_set_none(&hints);
|
||||
switch (state) {
|
||||
case XCB_ICCCM_WM_STATE_WITHDRAWN:
|
||||
xcb_icccm_wm_hints_set_withdrawn(&hints);
|
||||
break;
|
||||
case XCB_ICCCM_WM_STATE_NORMAL:
|
||||
xcb_icccm_wm_hints_set_normal(&hints);
|
||||
break;
|
||||
case XCB_ICCCM_WM_STATE_ICONIC:
|
||||
xcb_icccm_wm_hints_set_iconic(&hints);
|
||||
break;
|
||||
}
|
||||
xcb_icccm_set_wm_hints(wm.xcb_conn, window, &hints);
|
||||
}
|
||||
|
||||
xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window) {
|
||||
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(wm.xcb_conn, window);
|
||||
return xcb_get_geometry_reply(wm.xcb_conn, cookie, nullptr);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "action.h"
|
||||
@@ -22,9 +23,11 @@ void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property,
|
||||
char **out);
|
||||
void xwindow_set_wm_desktop(xcb_window_t window, uint32_t desktop);
|
||||
bool xwindow_get_wm_desktop(xcb_window_t window, uint32_t *desktop);
|
||||
void xwindow_kill_window(xcb_window_t window);
|
||||
|
||||
xcb_window_t xwindow_get_transient_for(xcb_window_t window);
|
||||
int32_t xwindow_get_state(xcb_window_t window);
|
||||
void xwindow_set_state(xcb_window_t window, xcb_icccm_wm_state_t state);
|
||||
xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window);
|
||||
xcb_get_window_attributes_reply_t *xwindow_get_attributes_reply(
|
||||
xcb_window_t window);
|
||||
|
||||
Reference in New Issue
Block a user