支持窗口最小化功能
This commit is contained in:
@@ -105,6 +105,14 @@ void toggle_client_maximize(const user_action_arg_t *arg) {
|
||||
client_set_maximize(wm.client_focused, !wm.client_focused->maximize);
|
||||
}
|
||||
|
||||
void toggle_client_minimize(const user_action_arg_t *arg) {
|
||||
client_t *client = wm.client_focused;
|
||||
if (arg->ptr) client = (client_t *)arg->ptr;
|
||||
if (!client) return;
|
||||
|
||||
client_set_minimize(client, !client->minimize);
|
||||
}
|
||||
|
||||
void kill_client(const user_action_arg_t *arg) {
|
||||
if (wm.client_focused) {
|
||||
client_kill(wm.client_focused);
|
||||
|
||||
@@ -13,6 +13,7 @@ typedef union user_action_arg_t {
|
||||
typedef enum click_area_t {
|
||||
click_none,
|
||||
click_tag,
|
||||
click_client_name,
|
||||
} click_area_t;
|
||||
|
||||
typedef enum modifier_t {
|
||||
@@ -60,4 +61,5 @@ 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 toggle_client_minimize(const user_action_arg_t *arg);
|
||||
void kill_client(const user_action_arg_t *arg);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
_XKB_RULES_NAMES
|
||||
|
||||
WM_CHANGE_STATE
|
||||
WM_DELETE_WINDOW
|
||||
WM_PROTOCOLS
|
||||
WM_TAKE_FOCUS
|
||||
|
||||
34
src/client.c
34
src/client.c
@@ -140,7 +140,7 @@ static inline void client_update_names(client_t *c) {
|
||||
}
|
||||
|
||||
static inline void client_init_geometry(client_t *c) {
|
||||
if (c->maximize || c->fullscreen) return;
|
||||
if (c->maximize || c->fullscreen || c->minimize) return;
|
||||
|
||||
area_t workarea = c->monitor->workarea;
|
||||
if (c->geometry.x + client_width(c) > workarea.x + workarea.width) {
|
||||
@@ -194,10 +194,10 @@ void client_manage(xcb_window_t window,
|
||||
c->geometry = c->old_geometry;
|
||||
c->old_border_width = geometry_reply->border_width;
|
||||
|
||||
{
|
||||
c->minimize = xwindow_get_state(window) == XCB_ICCCM_WM_STATE_ICONIC;
|
||||
|
||||
set_window_event_mask(window, false);
|
||||
xcb_map_window(wm.xcb_conn, window);
|
||||
}
|
||||
|
||||
client_update_names(c);
|
||||
xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role);
|
||||
client_update_wm_hints(c);
|
||||
@@ -242,7 +242,13 @@ 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);
|
||||
|
||||
if (c->minimize) {
|
||||
xwindow_set_state(window, XCB_ICCCM_WM_STATE_ICONIC);
|
||||
} else {
|
||||
xwindow_set_state(window, XCB_ICCCM_WM_STATE_NORMAL);
|
||||
xcb_map_window(wm.xcb_conn, window);
|
||||
}
|
||||
|
||||
monitor_arrange(c->monitor);
|
||||
monitor_draw_bar(c->monitor);
|
||||
@@ -469,6 +475,26 @@ void client_set_maximize(client_t *client, bool maximize) {
|
||||
client_focus(client);
|
||||
}
|
||||
|
||||
void client_set_minimize(client_t *client, bool minimize) {
|
||||
if (client->minimize == minimize) return;
|
||||
|
||||
client->minimize = minimize;
|
||||
if (minimize) {
|
||||
xwindow_set_state(client->window, XCB_ICCCM_WM_STATE_ICONIC);
|
||||
|
||||
xcb_grab_server(wm.xcb_conn);
|
||||
set_window_event_mask(client->window, true);
|
||||
xcb_unmap_window(wm.xcb_conn, client->window);
|
||||
set_window_event_mask(client->window, false);
|
||||
xcb_ungrab_server(wm.xcb_conn);
|
||||
} else {
|
||||
xwindow_set_state(client->window, XCB_ICCCM_WM_STATE_NORMAL);
|
||||
xcb_map_window(wm.xcb_conn, client->window);
|
||||
}
|
||||
monitor_arrange(client->monitor);
|
||||
client_focus(client);
|
||||
}
|
||||
|
||||
static void update_client_list(void) {
|
||||
xcb_connection_t *conn = wm.xcb_conn;
|
||||
xcb_window_t root = wm.screen->root;
|
||||
|
||||
@@ -29,6 +29,7 @@ static const char *const active_border_color = "#005577";
|
||||
|
||||
static const button_t button_list[] = {
|
||||
{click_tag, modifier_none, button_left, select_tag_of_current_monitor, {0}},
|
||||
{click_client_name, modifier_none, button_left, toggle_client_minimize, {0}},
|
||||
};
|
||||
|
||||
#define TAGKEYS(KEY, TAG) \
|
||||
|
||||
39
src/event.c
39
src/event.c
@@ -24,15 +24,22 @@ static void button_press(xcb_button_press_event_t *ev) {
|
||||
click_area_t click_area = click_none;
|
||||
user_action_arg_t arg = {0};
|
||||
|
||||
monitor_t *monitor = nullptr;
|
||||
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
|
||||
if (ev->event == m->bar_window) {
|
||||
if (wm.current_monitor != m) wm.current_monitor = m;
|
||||
monitor = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->event_x >= m->tag_extent.start &&
|
||||
ev->event_x <= m->tag_extent.end) {
|
||||
if (!monitor) return;
|
||||
|
||||
wm.current_monitor = monitor;
|
||||
if (ev->event_x >= monitor->tag_extent.start &&
|
||||
ev->event_x <= monitor->tag_extent.end) {
|
||||
click_area = click_tag;
|
||||
|
||||
for (tag_t *tag = m->tag_list; tag; tag = tag->next) {
|
||||
for (tag_t *tag = monitor->tag_list; tag; tag = tag->next) {
|
||||
if (ev->event_x >= tag->bar_extent.start &&
|
||||
ev->event_x <= tag->bar_extent.end) {
|
||||
arg.ui = tag->mask;
|
||||
@@ -40,9 +47,20 @@ static void button_press(xcb_button_press_event_t *ev) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (click_area == click_none) {
|
||||
for (task_in_tag_t *task = monitor->selected_tag->task_list; task;
|
||||
task = task->next) {
|
||||
if (ev->event_x >= task->bar_extent.start &&
|
||||
ev->event_x <= task->bar_extent.end) {
|
||||
click_area = click_client_name;
|
||||
arg.ptr = task->client;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (click_area == click_none) return;
|
||||
|
||||
for (int i = 0; i < countof(button_list); i++) {
|
||||
if (click_area == button_list[i].click_area &&
|
||||
@@ -209,6 +227,15 @@ static void client_message(xcb_client_message_event_t *ev) {
|
||||
ev->data.data32[2] == _NET_WM_STATE_MAXIMIZED_VERT) {
|
||||
client_set_maximize(c, get_bool_property(c->maximize, action));
|
||||
}
|
||||
} else if (ev->type == WM_CHANGE_STATE) {
|
||||
switch (ev->data.data32[0]) {
|
||||
case XCB_ICCCM_WM_STATE_ICONIC:
|
||||
client_set_minimize(c, true);
|
||||
break;
|
||||
case XCB_ICCCM_WM_STATE_NORMAL:
|
||||
client_set_minimize(c, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,14 +265,14 @@ static void destroy_notify(xcb_destroy_notify_event_t *ev) {
|
||||
|
||||
static void unmap_notify(xcb_unmap_notify_event_t *ev) {
|
||||
client_t *client = client_get_by_window(ev->window);
|
||||
if (client) {
|
||||
if (!client || client->minimize) return;
|
||||
|
||||
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) {
|
||||
/* 锁屏重新进入桌面后绘制 bar 内容以免 bar 不显示内容 */
|
||||
|
||||
Reference in New Issue
Block a user