build: add XInput2 library dependency for raw key event monitoring

This commit is contained in:
2026-01-26 23:47:23 +00:00
parent 725267fa00
commit 915870875d
19 changed files with 429 additions and 36 deletions
+3 -10
View File
@@ -1336,7 +1336,8 @@ unsigned long client_get_glow_text_color(Client *client)
if (client == NULL || !client->text_glow.active) {
return 0xFFFFFF;
}
return glow_color(client->text_glow.base_color, client->text_glow.phase);
float phase = dwn->ambient_phase + client->text_glow.phase;
return glow_color(client->text_glow.base_color, phase);
}
void client_update_animations(void)
@@ -1361,20 +1362,12 @@ void client_update_animations(void)
}
if (c->text_glow.active && c->workspace == (unsigned int)dwn->current_workspace) {
c->text_glow.phase += 0.01f * c->text_glow.speed;
c->text_glow.phase += 0.005f * c->text_glow.speed;
if (c->text_glow.phase > 6.283f) {
c->text_glow.phase -= 6.283f;
}
needs_redraw = true;
}
if (c->frame != None && c->workspace == (unsigned int)dwn->current_workspace) {
if (!(c->flags & CLIENT_MINIMIZED)) {
Workspace *ws = workspace_get(c->workspace);
bool focused = (ws != NULL && ws->focused == c);
decorations_render(c, focused);
}
}
}
if (needs_redraw) {
+11 -5
View File
@@ -64,7 +64,8 @@ void decorations_render_title_bar(Client *client, bool focused)
Workspace *ws = workspace_get(client->workspace);
bool is_focused = (ws != NULL && ws->focused == client);
unsigned long bg_color = is_focused ? colors->title_focused_bg : colors->title_unfocused_bg;
unsigned long base_bg = is_focused ? colors->title_focused_bg : colors->title_unfocused_bg;
unsigned long bg_color = ambient_glow_bg(base_bg, dwn->ambient_phase + PHASE_OFFSET_DECORATIONS);
unsigned long fg_color = client->taskbar_color;
fg_color = adjust_color_for_background(fg_color, bg_color);
@@ -173,11 +174,16 @@ void decorations_render_buttons(Client *client, bool focused)
const ColorScheme *colors = config_get_colors();
Workspace *ws = workspace_get(client->workspace);
bool is_focused = (ws != NULL && ws->focused == client);
unsigned long bg_color = is_focused ? colors->title_focused_bg : colors->title_unfocused_bg;
unsigned long base_bg = is_focused ? colors->title_focused_bg : colors->title_unfocused_bg;
unsigned long bg_color = ambient_glow_bg(base_bg, dwn->ambient_phase + PHASE_OFFSET_DECORATIONS);
unsigned long close_color = ambient_glow_accent(0xff0055, dwn->ambient_phase + PHASE_OFFSET_DECORATIONS);
unsigned long max_color = ambient_glow_accent(0x00ff00, dwn->ambient_phase + PHASE_OFFSET_DECORATIONS);
unsigned long min_color = ambient_glow_accent(0xffff00, dwn->ambient_phase + PHASE_OFFSET_DECORATIONS);
XSetForeground(dpy, dwn->gc, bg_color);
XFillRectangle(dpy, client->frame, dwn->gc, close_x, button_y, BUTTON_SIZE, BUTTON_SIZE);
XSetForeground(dpy, dwn->gc, 0xff0055); // Neon Red/Pink
XSetForeground(dpy, dwn->gc, close_color);
XDrawLine(dpy, client->frame, dwn->gc,
close_x + 3, button_y + 3,
close_x + BUTTON_SIZE - 4, button_y + BUTTON_SIZE - 4);
@@ -187,14 +193,14 @@ void decorations_render_buttons(Client *client, bool focused)
XSetForeground(dpy, dwn->gc, bg_color);
XFillRectangle(dpy, client->frame, dwn->gc, max_x, button_y, BUTTON_SIZE, BUTTON_SIZE);
XSetForeground(dpy, dwn->gc, 0x00ff00); // Neon Green
XSetForeground(dpy, dwn->gc, max_color);
XDrawRectangle(dpy, client->frame, dwn->gc,
max_x + 3, button_y + 3,
BUTTON_SIZE - 7, BUTTON_SIZE - 7);
XSetForeground(dpy, dwn->gc, bg_color);
XFillRectangle(dpy, client->frame, dwn->gc, min_x, button_y, BUTTON_SIZE, BUTTON_SIZE);
XSetForeground(dpy, dwn->gc, 0xffff00); // Neon Yellow
XSetForeground(dpy, dwn->gc, min_color);
XDrawLine(dpy, client->frame, dwn->gc,
min_x + 3, button_y + BUTTON_SIZE - 5,
min_x + BUTTON_SIZE - 4, button_y + BUTTON_SIZE - 5);
+1
View File
@@ -436,6 +436,7 @@ void keys_handle_press(XKeyEvent *ev)
KeySym keysym = XLookupKeysym(ev, 0);
if (keysym == XK_Super_L || keysym == XK_Super_R) {
super_pressed = true;
super_used_in_combo = false;
+108 -4
View File
@@ -31,10 +31,14 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <math.h>
#include <sys/select.h>
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/keysymdef.h>
#include <X11/XKBlib.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/XInput2.h>
DWNState *dwn = NULL;
static DWNState dwn_state;
@@ -134,6 +138,71 @@ static bool check_other_wm(void)
return wm_detected != 0;
}
static void init_xinput2(void)
{
int event, error;
if (!XQueryExtension(dwn->display, "XInputExtension",
&dwn->xi2_opcode, &event, &error)) {
LOG_WARN("XInput2 extension not available - key counting disabled");
dwn->xi2_opcode = 0;
return;
}
int major = 2, minor = 0;
if (XIQueryVersion(dwn->display, &major, &minor) != Success) {
LOG_WARN("XInput2 version 2.0 not available - key counting disabled");
dwn->xi2_opcode = 0;
return;
}
XIEventMask evmask;
unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0};
evmask.deviceid = XIAllMasterDevices;
evmask.mask_len = sizeof(mask);
evmask.mask = mask;
XISetMask(mask, XI_RawKeyPress);
XISetMask(mask, XI_RawKeyRelease);
XISelectEvents(dwn->display, dwn->root, &evmask, 1);
LOG_INFO("XInput2 initialized for raw key event monitoring");
}
static void handle_xi2_event(XGenericEventCookie *cookie)
{
if (cookie->type != GenericEvent || cookie->extension != dwn->xi2_opcode) {
return;
}
if (!XGetEventData(dwn->display, cookie)) {
return;
}
if (cookie->evtype == XI_RawKeyPress) {
XIRawEvent *raw = (XIRawEvent *)cookie->data;
KeyCode keycode = (KeyCode)raw->detail;
KeySym keysym = XkbKeycodeToKeysym(dwn->display, keycode, 0, 0);
if (keysym != XK_Super_L && keysym != XK_Super_R &&
keysym != XK_Alt_L && keysym != XK_Alt_R &&
keysym != XK_Control_L && keysym != XK_Control_R &&
keysym != XK_Shift_L && keysym != XK_Shift_R &&
keysym != XK_Caps_Lock && keysym != XK_Num_Lock &&
keysym != XK_Scroll_Lock) {
dwn->key_press_count++;
dwn->typing_activity_time = get_time_ms();
if (keysym == XK_BackSpace || keysym == XK_Delete) {
dwn->key_delete_flicker_time = get_time_ms();
}
}
}
XFreeEventData(dwn->display, cookie);
}
static void init_monitors(void)
{
if (!XineramaIsActive(dwn->display)) {
@@ -790,6 +859,8 @@ int dwn_init(void)
init_monitors();
init_xinput2();
workspace_init();
decorations_init();
@@ -842,6 +913,10 @@ int dwn_init(void)
dwn->running = true;
dwn->ambient_phase = 0.0f;
dwn->ambient_speed = 0.5f;
dwn->typing_activity_time = 0;
LOG_INFO("DWN initialized successfully");
return 0;
@@ -913,6 +988,11 @@ void dwn_run(void)
while (XPending(dwn->display)) {
XEvent ev;
XNextEvent(dwn->display, &ev);
if (ev.type == GenericEvent && dwn->xi2_opcode > 0) {
handle_xi2_event(&ev.xcookie);
}
dwn_handle_event(&ev);
}
@@ -930,13 +1010,39 @@ void dwn_run(void)
demo_update();
long now = get_time_ms();
float speed_multiplier = 1.0f;
if (now - dwn->typing_activity_time < 500) {
speed_multiplier = 3.0f;
}
dwn->ambient_phase += 0.008f * dwn->ambient_speed * speed_multiplier;
if (dwn->ambient_phase > 6.283f) {
dwn->ambient_phase -= 6.283f;
}
client_update_animations();
Window root_ret, child_ret;
int root_x, root_y, win_x, win_y;
unsigned int mask_ret;
if (XQueryPointer(dwn->display, dwn->root, &root_ret, &child_ret,
&root_x, &root_y, &win_x, &win_y, &mask_ret)) {
if (dwn->mouse_tracking_initialized) {
int dx = root_x - dwn->last_mouse_x;
int dy = root_y - dwn->last_mouse_y;
dwn->mouse_distance_pixels += sqrt((double)(dx * dx + dy * dy));
}
dwn->last_mouse_x = root_x;
dwn->last_mouse_y = root_y;
dwn->mouse_tracking_initialized = true;
}
notifications_update();
if (dwn->pending_focus_client != NULL) {
long now_focus = get_time_ms();
if (now_focus >= dwn->pending_focus_time) {
if (now >= dwn->pending_focus_time) {
Workspace *ws = workspace_get_current();
if (ws != NULL && ws->focused != dwn->pending_focus_client) {
if (dwn->pending_focus_client->workspace == (unsigned int)dwn->current_workspace) {
@@ -947,8 +1053,6 @@ void dwn_run(void)
}
}
long now = get_time_ms();
if (now - last_news_update >= 16) {
news_update();
panel_render_all();
+2 -1
View File
@@ -645,6 +645,7 @@ void news_render(Panel *panel, int x, int max_width, int *used_width)
unsigned long article_color = news_sentiment_color(
news_state.articles[current_article].sentiment);
article_color = ambient_glow_bg(article_color, dwn->ambient_phase + PHASE_OFFSET_NEWS);
if (draw_x + news_state.display_widths[current_article] > x) {
news_draw_text_clipped(panel->buffer, draw_x, text_y, display_text,
@@ -654,7 +655,7 @@ void news_render(Panel *panel, int x, int max_width, int *used_width)
if (draw_x < x + max_width) {
news_draw_text_clipped(panel->buffer, draw_x, text_y, NEWS_SEPARATOR,
colors->panel_fg, &clip_rect);
ambient_glow_bg(colors->panel_fg, dwn->ambient_phase + PHASE_OFFSET_NEWS), &clip_rect);
}
draw_x += separator_width;
+227 -12
View File
@@ -19,6 +19,8 @@
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <ctype.h>
#include <X11/Xft/Xft.h>
#define PANEL_PADDING 12
@@ -42,12 +44,18 @@ typedef struct {
float load_15min;
unsigned long long prev_idle;
unsigned long long prev_total;
char top_mem_process[64];
int top_mem_percent;
} SystemStats;
static SystemStats sys_stats = {0};
static void panel_render_system_stats(Panel *panel, int x, int *width);
static int panel_calculate_stats_width(void);
static void panel_render_top_mem_process(Panel *panel, int x, int *width);
static void panel_render_key_counter(Panel *panel, int x, int *width);
static void panel_render_mouse_distance(Panel *panel, int x, int *width);
static void update_top_memory_process(void);
static int panel_text_width(const char *text, int len)
@@ -265,7 +273,8 @@ void panel_render(Panel *panel)
Display *dpy = dwn->display;
const ColorScheme *colors = config_get_colors();
XSetForeground(dpy, dwn->gc, colors->panel_bg);
unsigned long bg = ambient_glow_bg(colors->panel_bg, dwn->ambient_phase + PHASE_OFFSET_PANEL_BG);
XSetForeground(dpy, dwn->gc, bg);
XFillRectangle(dpy, panel->buffer, dwn->gc, 0, 0, panel->width, panel->height);
int x = PANEL_PADDING;
@@ -294,11 +303,24 @@ void panel_render(Panel *panel)
int date_width = 0;
if (dwn->xft_font != NULL || dwn->font != NULL) {
int text_y = panel_text_y(panel->height);
unsigned long date_fg = ambient_glow_bg(colors->panel_fg, dwn->ambient_phase + PHASE_OFFSET_CLOCK);
panel_draw_text(panel->buffer, x, text_y, date_buffer,
strlen(date_buffer), colors->panel_fg);
strlen(date_buffer), date_fg);
date_width = panel_text_width(date_buffer, strlen(date_buffer));
}
int key_counter_width = 0;
int key_counter_x = PANEL_PADDING + date_width + WIDGET_SPACING;
panel_render_key_counter(panel, key_counter_x, &key_counter_width);
int mouse_dist_width = 0;
int mouse_dist_x = key_counter_x + key_counter_width + WIDGET_SPACING;
panel_render_mouse_distance(panel, mouse_dist_x, &mouse_dist_width);
int top_mem_width = 0;
int top_mem_x = mouse_dist_x + mouse_dist_width + WIDGET_SPACING;
panel_render_top_mem_process(panel, top_mem_x, &top_mem_width);
int clock_width = panel_text_width(clock_buffer, strlen(clock_buffer));
int stats_width = panel_calculate_stats_width();
@@ -308,7 +330,7 @@ void panel_render(Panel *panel)
int stats_x = clock_x - stats_width - WIDGET_SPACING;
panel_render_system_stats(panel, stats_x, &width);
int news_start = PANEL_PADDING + date_width + WIDGET_SPACING * 2;
int news_start = top_mem_x + top_mem_width + WIDGET_SPACING;
int news_max_width = stats_x - news_start - WIDGET_SPACING;
if (news_max_width > 100) {
int news_width = 0;
@@ -348,8 +370,10 @@ void panel_render_workspaces(Panel *panel, int x, int *width)
bool active = (i == dwn->current_workspace);
bool has_clients = !workspace_is_empty(i);
unsigned long bg = active ? colors->workspace_active : colors->panel_bg;
XSetForeground(dpy, dwn->gc, bg);
unsigned long bg_color = active ?
ambient_glow_accent(colors->workspace_active, dwn->ambient_phase + PHASE_OFFSET_WORKSPACES) :
ambient_glow_bg(colors->panel_bg, dwn->ambient_phase + PHASE_OFFSET_WORKSPACES);
XSetForeground(dpy, dwn->gc, bg_color);
XFillRectangle(dpy, panel->buffer, dwn->gc,
x + i * WORKSPACE_WIDTH, 0,
WORKSPACE_WIDTH, panel->height);
@@ -358,7 +382,7 @@ void panel_render_workspaces(Panel *panel, int x, int *width)
snprintf(num, sizeof(num), "%d", i + 1);
unsigned long fg = active ? colors->panel_bg :
(has_clients ? colors->panel_fg : colors->workspace_inactive);
ambient_glow_bg(has_clients ? colors->panel_fg : colors->workspace_inactive, dwn->ambient_phase + PHASE_OFFSET_WORKSPACES);
int text_x = x + i * WORKSPACE_WIDTH + (WORKSPACE_WIDTH - panel_text_width(num, strlen(num))) / 2;
panel_draw_text(panel->buffer, text_x, text_y, num, strlen(num), fg);
@@ -454,7 +478,7 @@ void panel_render_taskbar(Panel *panel, int x, int *width)
unsigned long fg;
if (minimized) {
fg = colors->panel_fg;
fg = ambient_glow_bg(colors->panel_fg, dwn->ambient_phase + PHASE_OFFSET_TASKBAR);
} else {
fg = client_get_glow_text_color(c);
}
@@ -483,8 +507,9 @@ void panel_render_clock(Panel *panel, int x, int *width)
const ColorScheme *colors = config_get_colors();
int text_y = panel_text_y(panel->height);
unsigned long fg = ambient_glow_bg(colors->panel_fg, dwn->ambient_phase + PHASE_OFFSET_CLOCK);
panel_draw_text(panel->buffer, x, text_y, clock_buffer,
strlen(clock_buffer), colors->panel_fg);
strlen(clock_buffer), fg);
*width = panel_text_width(clock_buffer, strlen(clock_buffer));
}
@@ -511,8 +536,8 @@ void panel_render_layout_indicator(Panel *panel, int x, int *width)
Workspace *ws = workspace_get_current();
const char *symbol = layout_get_symbol(ws != NULL ? ws->layout : LAYOUT_TILING);
panel_draw_text(panel->buffer, x, text_y, symbol, strlen(symbol),
colors->workspace_active);
unsigned long fg = ambient_glow_accent(colors->workspace_active, dwn->ambient_phase + PHASE_OFFSET_WORKSPACES);
panel_draw_text(panel->buffer, x, text_y, symbol, strlen(symbol), fg);
*width = panel_text_width(symbol, strlen(symbol));
}
@@ -531,8 +556,8 @@ void panel_render_ai_status(Panel *panel, int x, int *width)
const char *status = dwn->ai_enabled ? "[AI]" : "";
panel_draw_text(panel->buffer, x, text_y, status, strlen(status),
colors->workspace_active);
unsigned long fg = ambient_glow_accent(colors->workspace_active, dwn->ambient_phase + PHASE_OFFSET_SYSTRAY);
panel_draw_text(panel->buffer, x, text_y, status, strlen(status), fg);
*width = panel_text_width(status, strlen(status));
}
@@ -779,6 +804,74 @@ void panel_update_system_stats(void)
}
fclose(fp);
}
update_top_memory_process();
}
static void update_top_memory_process(void)
{
DIR *proc_dir = opendir("/proc");
if (proc_dir == NULL) {
sys_stats.top_mem_process[0] = '\0';
sys_stats.top_mem_percent = 0;
return;
}
unsigned long max_rss = 0;
char max_name[64] = "";
unsigned long mem_total_kb = (unsigned long)sys_stats.mem_total_mb * 1024;
struct dirent *entry;
while ((entry = readdir(proc_dir)) != NULL) {
bool is_pid = true;
size_t name_len = 0;
for (int i = 0; entry->d_name[i] != '\0'; i++) {
if (!isdigit((unsigned char)entry->d_name[i])) {
is_pid = false;
break;
}
name_len++;
}
if (!is_pid || name_len > 20) continue;
char status_path[64];
snprintf(status_path, sizeof(status_path), "/proc/%.20s/status", entry->d_name);
FILE *fp = fopen(status_path, "r");
if (fp == NULL) continue;
char line[256];
char name[64] = "";
unsigned long rss_kb = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
if (strncmp(line, "Name:", 5) == 0) {
char *start = line + 5;
while (*start == ' ' || *start == '\t') start++;
size_t len = strlen(start);
if (len > 0 && start[len - 1] == '\n') start[len - 1] = '\0';
snprintf(name, sizeof(name), "%s", start);
} else if (strncmp(line, "VmRSS:", 6) == 0) {
sscanf(line + 6, " %lu", &rss_kb);
break;
}
}
fclose(fp);
if (rss_kb > max_rss && name[0] != '\0') {
max_rss = rss_kb;
snprintf(max_name, sizeof(max_name), "%s", name);
}
}
closedir(proc_dir);
snprintf(sys_stats.top_mem_process, sizeof(sys_stats.top_mem_process), "%s", max_name);
if (mem_total_kb > 0) {
sys_stats.top_mem_percent = (int)((max_rss * 100) / mem_total_kb);
} else {
sys_stats.top_mem_percent = 0;
}
}
static int panel_calculate_stats_width(void)
@@ -852,6 +945,7 @@ static void panel_render_system_stats(Panel *panel, int x, int *width)
} else if (sys_stats.cpu_percent >= 70) {
cpu_color = 0xFFA500;
}
cpu_color = ambient_glow_bg(cpu_color, dwn->ambient_phase + PHASE_OFFSET_STATS);
len = snprintf(stats_buf, sizeof(stats_buf), "CPU:%2d%%", sys_stats.cpu_percent);
panel_draw_text(panel->buffer, current_x, text_y, stats_buf, len, cpu_color);
@@ -863,6 +957,7 @@ static void panel_render_system_stats(Panel *panel, int x, int *width)
} else if (sys_stats.mem_percent >= 75) {
mem_color = 0xFFA500;
}
mem_color = ambient_glow_bg(mem_color, dwn->ambient_phase + PHASE_OFFSET_STATS);
if (sys_stats.mem_total_mb >= 1024) {
len = snprintf(stats_buf, sizeof(stats_buf), "MEM:%.1fG/%dG",
@@ -880,6 +975,7 @@ static void panel_render_system_stats(Panel *panel, int x, int *width)
} else if (sys_stats.load_1min >= 2.0f) {
load_color = 0xFFA500;
}
load_color = ambient_glow_bg(load_color, dwn->ambient_phase + PHASE_OFFSET_STATS);
len = snprintf(stats_buf, sizeof(stats_buf), "Load:%.2f %.2f %.2f",
sys_stats.load_1min, sys_stats.load_5min, sys_stats.load_15min);
@@ -896,6 +992,7 @@ static void panel_render_system_stats(Panel *panel, int x, int *width)
} else if (multi_bat.any_charging) {
bat_color = colors->workspace_active;
}
bat_color = ambient_glow_bg(bat_color, dwn->ambient_phase + PHASE_OFFSET_STATS);
const char *bat_icon = multi_bat.any_charging ? "[+]" : "[=]";
if (multi_bat.count == 1) {
@@ -919,6 +1016,124 @@ static void panel_render_system_stats(Panel *panel, int x, int *width)
*width = current_x - x;
}
static void panel_render_key_counter(Panel *panel, int x, int *width)
{
if (panel == NULL || width == NULL) {
*width = 0;
return;
}
if (dwn->xft_font == NULL && dwn->font == NULL) {
*width = 0;
return;
}
const ColorScheme *colors = config_get_colors();
int text_y = panel_text_y(panel->height);
char buf[32];
unsigned long count = dwn->key_press_count;
int len;
if (count >= 1000000) {
len = snprintf(buf, sizeof(buf), "Keys:%.1fM", count / 1000000.0);
} else if (count >= 1000) {
len = snprintf(buf, sizeof(buf), "Keys:%.1fK", count / 1000.0);
} else {
len = snprintf(buf, sizeof(buf), "Keys:%lu", count);
}
long now = get_time_ms();
bool flickering = (now - dwn->key_delete_flicker_time) < 100;
unsigned long fg;
if (flickering) {
unsigned long base = colors->panel_fg;
int r = (int)((base >> 16) & 0xFF);
int g = (int)((base >> 8) & 0xFF);
int b = (int)(base & 0xFF);
r = r + (255 - r) / 2;
g = g + (255 - g) / 2;
b = b + (255 - b) / 2;
fg = ((unsigned long)r << 16) | ((unsigned long)g << 8) | (unsigned long)b;
} else {
fg = ambient_glow_bg(colors->panel_fg,
dwn->ambient_phase + PHASE_OFFSET_KEY_COUNTER);
}
if (flickering) {
panel_draw_text_bold(panel->buffer, x, text_y, buf, len, fg);
} else {
panel_draw_text(panel->buffer, x, text_y, buf, len, fg);
}
*width = panel_text_width(buf, len);
}
static void panel_render_mouse_distance(Panel *panel, int x, int *width)
{
if (panel == NULL || width == NULL) {
*width = 0;
return;
}
if (dwn->xft_font == NULL && dwn->font == NULL) {
*width = 0;
return;
}
const ColorScheme *colors = config_get_colors();
int text_y = panel_text_y(panel->height);
char buf[32];
double cm = dwn->mouse_distance_pixels / 37.8;
int len;
if (cm >= 100000.0) {
len = snprintf(buf, sizeof(buf), "Mouse:%.2fkm", cm / 100000.0);
} else if (cm >= 100.0) {
len = snprintf(buf, sizeof(buf), "Mouse:%.1fm", cm / 100.0);
} else {
len = snprintf(buf, sizeof(buf), "Mouse:%.0fcm", cm);
}
unsigned long fg = ambient_glow_bg(colors->panel_fg,
dwn->ambient_phase + PHASE_OFFSET_MOUSE_DIST);
panel_draw_text(panel->buffer, x, text_y, buf, len, fg);
*width = panel_text_width(buf, len);
}
static void panel_render_top_mem_process(Panel *panel, int x, int *width)
{
if (panel == NULL || width == NULL) {
*width = 0;
return;
}
if (dwn->xft_font == NULL && dwn->font == NULL) {
*width = 0;
return;
}
if (sys_stats.top_mem_process[0] == '\0') {
*width = 0;
return;
}
const ColorScheme *colors = config_get_colors();
int text_y = panel_text_y(panel->height);
unsigned long color = colors->panel_fg;
if (sys_stats.top_mem_percent >= 50) {
color = colors->workspace_urgent;
} else if (sys_stats.top_mem_percent >= 25) {
color = 0xFFA500;
}
color = ambient_glow_bg(color, dwn->ambient_phase + PHASE_OFFSET_TOP_MEM);
char buf[128];
int len = snprintf(buf, sizeof(buf), "%s %d%%",
sys_stats.top_mem_process, sys_stats.top_mem_percent);
panel_draw_text(panel->buffer, x, text_y, buf, len, color);
*width = panel_text_width(buf, len);
}
void panel_init_systray(void)
{
+4 -1
View File
@@ -558,7 +558,8 @@ void volume_slider_render(VolumeSlider *slider)
int text_width = get_text_width(vol_text);
int text_x = (slider->width - text_width) / 2;
draw_utf8_text(slider->window, text_x, slider->height - 4, vol_text, colors->panel_fg);
draw_utf8_text(slider->window, text_x, slider->height - 4, vol_text,
ambient_glow_bg(colors->panel_fg, dwn->ambient_phase + PHASE_OFFSET_SYSTRAY));
XFlush(dpy);
}
@@ -677,6 +678,7 @@ void systray_render(Panel *panel, int x, int *width)
snprintf(audio_label, sizeof(audio_label), "%s%d%%", audio_icon, audio_snap.volume);
unsigned long audio_color = audio_snap.muted ? colors->workspace_inactive : colors->panel_fg;
audio_color = ambient_glow_bg(audio_color, dwn->ambient_phase + PHASE_OFFSET_SYSTRAY);
draw_utf8_text(panel->buffer, current_x, text_y, audio_label, audio_color);
current_x += get_text_width(audio_label) + SYSTRAY_SPACING;
@@ -692,6 +694,7 @@ void systray_render(Panel *panel, int x, int *width)
}
unsigned long wifi_color = wifi_snap.connected ? colors->panel_fg : colors->workspace_inactive;
wifi_color = ambient_glow_bg(wifi_color, dwn->ambient_phase + PHASE_OFFSET_SYSTRAY);
draw_utf8_text(panel->buffer, current_x, text_y, wifi_label, wifi_color);
current_x += get_text_width(wifi_label);
+44
View File
@@ -818,3 +818,47 @@ unsigned long glow_color(unsigned long base, float phase)
return rgb_to_pixel(r, g, b);
}
unsigned long ambient_glow_bg(unsigned long base, float phase)
{
int r, g, b;
color_to_rgb(base, &r, &g, &b);
float mod = 0.25f * sinf(phase);
r = r + (int)(r * mod);
g = g + (int)(g * mod);
b = b + (int)(b * mod);
if (r > 255) r = 255;
if (r < 0) r = 0;
if (g > 255) g = 255;
if (g < 0) g = 0;
if (b > 255) b = 255;
if (b < 0) b = 0;
return rgb_to_pixel(r, g, b);
}
unsigned long ambient_glow_accent(unsigned long base, float phase)
{
int r, g, b;
color_to_rgb(base, &r, &g, &b);
float mod_r = 0.45f * sinf(phase);
float mod_g = 0.45f * sinf(phase + 2.094f);
float mod_b = 0.45f * sinf(phase + 4.189f);
r = r + (int)(r * mod_r);
g = g + (int)(g * mod_g);
b = b + (int)(b * mod_b);
if (r > 255) r = 255;
if (r < 0) r = 0;
if (g > 255) g = 255;
if (g < 0) g = 0;
if (b > 255) b = 255;
if (b < 0) b = 0;
return rgb_to_pixel(r, g, b);
}