绘制任务栏
This commit is contained in:
68
src/client.c
68
src/client.c
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
26
src/event.c
26
src/event.c
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user