绘制任务栏

This commit is contained in:
2025-12-09 02:19:05 +08:00
parent 503135830e
commit 4ca37760e8
4 changed files with 117 additions and 7 deletions

View File

@@ -8,6 +8,7 @@
#include <xcb/xproto.h>
#include "atoms-extern.h"
#include "monitor.h"
#include "types.h"
#include "utils.h"
#include "wm.h"
@@ -56,17 +57,58 @@ task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag) {
return nullptr;
}
static void client_add_to_tag(client_t *client, tag_t *tag) {
if (client_get_task_in_tag(client, tag)) return;
task_in_tag_t *task = p_new(task_in_tag_t, 1);
task->client = client;
task->next = tag->task_list;
tag->task_list = task;
}
static void client_remove_from_tag(client_t *client, tag_t *tag) {
for (task_in_tag_t **task = &tag->task_list; *task; task = &(*task)->next) {
if ((*task)->client != client) continue;
p_delete(task);
*task = (*task)->next;
}
}
static inline void client_wipe(client_t *client) {
p_delete(&client->class);
p_delete(&client->instance);
p_delete(&client->name);
p_delete(&client->icon_name);
p_delete(&client->net_name);
p_delete(&client->net_icon_name);
p_delete(&client->role);
p_delete(&client);
}
static inline void client_tags_apply(client_t *client) {
for (tag_t *tag = client->monitor->tag_list; tag; tag = tag->next) {
if (client->tags & tag->mask) {
client_add_to_tag(client, tag);
} else {
client_remove_from_tag(client, tag);
}
}
if (client->tags == 0) client_wipe(client);
}
static inline void client_update_names(client_t *c) {
xwindow_get_text_property(c->window, WM_NAME, &c->name);
xwindow_get_text_property(c->window, WM_ICON_NAME, &c->icon_name);
xwindow_get_text_property(c->window, _NET_WM_NAME, &c->net_name);
xwindow_get_text_property(c->window, _NET_WM_ICON_NAME, &c->net_icon_name);
}
void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply) {
client_t *c = p_new(client_t, 1);
c->window = window;
c->name = xwindow_get_text_property(c->window, WM_NAME);
c->icon_name = xwindow_get_text_property(c->window, WM_ICON_NAME);
c->net_name = xwindow_get_text_property(c->window, _NET_WM_NAME);
c->net_icon_name = xwindow_get_text_property(c->window, _NET_WM_ICON_NAME);
c->role = xwindow_get_text_property(c->window, WM_WINDOW_ROLE);
client_attach_list(c);
client_attach_stack(c);
@@ -79,6 +121,7 @@ void client_manage(xcb_window_t window,
c->instance = strdup(prop.instance_name);
xcb_icccm_get_wm_class_reply_wipe(&prop);
}
xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role);
}
{
@@ -96,8 +139,11 @@ void client_manage(xcb_window_t window,
c->monitor = wm.current_monitor;
c->tags = c->monitor->selected_tag->mask;
}
client_tags_apply(c);
}
monitor_arrange(c->monitor);
{
const xcb_params_cw_t params = {
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
@@ -109,9 +155,19 @@ void client_manage(xcb_window_t window,
xcb_map_window(wm.xcb_conn, window);
}
client_update_names(c);
monitor_draw_bar(c->monitor);
xcb_flush(wm.xcb_conn);
}
char **client_get_task_title(client_t *client) {
if (client->net_icon_name) return &client->net_icon_name;
if (client->net_name) return &client->net_name;
if (client->icon_name) return &client->icon_name;
if (client->name) return &client->name;
return nullptr;
}
bool client_need_layout(client_t *client) {
if (client->floating || client->fullscreen || client->maximize ||
client->minimize) {

View File

@@ -9,6 +9,7 @@ client_t *client_get_by_window(xcb_window_t window);
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag);
void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply);
char **client_get_task_title(client_t *client);
bool client_need_layout(client_t *client);
void client_send_to_tag(client_t *client, uint32_t tag_mask);

View File

@@ -2,7 +2,7 @@
#include <glib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h>
@@ -10,12 +10,15 @@
#include <xkbcommon/xkbcommon.h>
#include "action.h"
#include "atoms-extern.h"
#include "client.h"
#include "default_config.h"
#include "monitor.h"
#include "types.h"
#include "utils.h"
#include "wm.h"
#include "xkb.h"
#include "xwindow.h"
static void button_press(xcb_button_press_event_t *ev) {
click_area_t click_area = click_none;
@@ -116,6 +119,26 @@ static void map_request(xcb_map_request_event_t *ev) {
p_delete(&wa_reply);
}
static void property_notify(xcb_property_notify_event_t *ev) {
client_t *client = client_get_by_window(ev->window);
if (client == nullptr) return;
if (ev->atom == WM_NAME) {
xwindow_get_text_property(ev->window, ev->atom, &client->name);
monitor_draw_bar(client->monitor);
} else if (ev->atom == WM_ICON_NAME) {
if (client->icon_name) p_delete(&client->icon_name);
xwindow_get_text_property(ev->window, ev->atom, &client->icon_name);
monitor_draw_bar(client->monitor);
} else if (ev->atom == _NET_WM_NAME) {
xwindow_get_text_property(ev->window, ev->atom, &client->net_name);
monitor_draw_bar(client->monitor);
} else if (ev->atom == _NET_WM_ICON_NAME) {
xwindow_get_text_property(ev->window, ev->atom, &client->net_icon_name);
monitor_draw_bar(client->monitor);
}
}
static void handle_xcb_event(xcb_generic_event_t *event) {
uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(event);
const char *label = xcb_event_get_label(event_type);
@@ -133,6 +156,7 @@ static void handle_xcb_event(xcb_generic_event_t *event) {
EVENT(XCB_KEY_RELEASE, key_press);
EVENT(XCB_CONFIGURE_REQUEST, configure_request);
EVENT(XCB_MAP_REQUEST, map_request);
EVENT(XCB_PROPERTY_NOTIFY, property_notify);
#undef EVENT
}

View File

@@ -197,6 +197,34 @@ static void monitor_draw_layout_symbol(monitor_t *monitor) {
}
}
static void monitor_draw_tasks(monitor_t *monitor) {
task_in_tag_t *task_list = monitor->selected_tag->task_list;
if (!task_list) return;
uint16_t task_count = 0;
for (task_in_tag_t *task = task_list; task; task = task->next) ++task_count;
if (task_count == 0) return;
int16_t x = monitor->layout_symbol_extent.end;
uint16_t task_width = (monitor->geometry.width - x) / task_count;
for (task_in_tag_t *task = task_list; task; task = task->next) {
task->bar_extent.start = x;
task->bar_extent.end = x + task_width;
x += task_width;
char **title = client_get_task_title(task->client);
if (title == nullptr || *title == nullptr) continue;
color_t *color = &wm.color_set.active_tag_color;
area_t area = {
.x = task->bar_extent.start,
.y = monitor->geometry.y,
.width = task_width,
.height = wm.bar_height,
};
draw_text(monitor->bar_cr, *title, color, area, false);
}
}
void monitor_draw_bar(monitor_t *monitor) {
cairo_t *cr = monitor->bar_cr;
uint16_t height = wm.bar_height;
@@ -210,6 +238,7 @@ void monitor_draw_bar(monitor_t *monitor) {
monitor_draw_tags(monitor);
monitor_draw_layout_symbol(monitor);
monitor_draw_tasks(monitor);
}
void monitor_arrange(monitor_t *monitor) {