diff
extras/bar.c | 64 +++++++++++++++++++++++++++++-------
extras/bar.h | 2 ++
wm.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wmc.c | 38 +++++++++++++++++++--
4 files changed, 196 insertions(+), 14 deletions(-)
diff --git a/extras/bar.c b/extras/bar.c
index a966298..e67898c 100644
--- a/extras/bar.c
+++ b/extras/bar.c
@@ -1,4 +1,5 @@
#include <X11/Xlib.h>
+#include <X11/Xutil.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
@@ -33,12 +34,18 @@ static int bar_monitor_count;
static int bar_margin_x;
static int bar_margin_y;
static int bar_is_bottom;
+static unsigned long bar_fg_color;
+static unsigned long bar_bg_color;
+static unsigned long bar_sel_fg_color;
+static unsigned long bar_sel_bg_color;
+static unsigned long bar_sel_accent_color;
static int bar_tags[max_tags];
static char bar_status[max_status_len];
static char bar_title[max_title_len];
static struct bar_monitor bar_monitors[max_monitors];
void bar_reconfigure(void);
+static unsigned long bar_alloc_color(const char *color_name, unsigned long fallback);
static int
bar_text_width(const char *text)
@@ -118,13 +125,11 @@ bar_load_monitors(void)
static void
bar_create_windows(void)
{
- unsigned long black;
XSetWindowAttributes attrs;
int i, window_x, window_y, window_width;
- black = BlackPixel(bar_display, bar_screen);
attrs.override_redirect = True;
- attrs.background_pixel = black;
+ attrs.background_pixel = bar_bg_color;
attrs.event_mask = ExposureMask;
for (i = 0; i < bar_monitor_count; i++) {
window_x = bar_monitors[i].x + bar_margin_x;
@@ -157,6 +162,11 @@ bar_init(Display *display, Window root_window)
return 0;
bar_gc = XCreateGC(display, root_window, 0, NULL);
XSetFont(display, bar_gc, bar_font->fid);
+ bar_fg_color = bar_alloc_color("#222222", BlackPixel(display, bar_screen));
+ bar_bg_color = bar_alloc_color("#ffffff", WhitePixel(display, bar_screen));
+ bar_sel_fg_color = bar_alloc_color("#111111", BlackPixel(display, bar_screen));
+ bar_sel_bg_color = bar_alloc_color("#dfe8ff", WhitePixel(display, bar_screen));
+ bar_sel_accent_color = bar_alloc_color("#005fcc", BlackPixel(display, bar_screen));
if (!bar_load_monitors())
return 0;
bar_create_windows();
@@ -194,40 +204,37 @@ bar_set_title(const char *title)
void
bar_draw(void)
{
- unsigned long white, black;
int m, x, i, tw, tagw, title_x, status_x, bar_width;
char tag_text[8];
if (bar_display == NULL || bar_monitor_count < 1)
return;
- white = WhitePixel(bar_display, bar_screen);
- black = BlackPixel(bar_display, bar_screen);
for (m = 0; m < bar_monitor_count; m++) {
if (bar_monitors[m].window == None)
continue;
bar_width = bar_monitors[m].bar_width;
- bar_draw_rect(bar_monitors[m].window, black, 0, 0, bar_width, bar_height);
+ bar_draw_rect(bar_monitors[m].window, bar_bg_color, 0, 0, bar_width, bar_height);
x = 0;
for (i = 0; i < bar_tag_count; i++) {
snprintf(tag_text, sizeof(tag_text), "%d", bar_tags[i]);
tw = bar_text_width(tag_text);
tagw = tw + (bar_padding * 2);
if (i == bar_selected_tag) {
- bar_draw_rect(bar_monitors[m].window, white, x, 2, tagw, bar_height - 4);
- bar_draw_text(bar_monitors[m].window, black, x + bar_padding, bar_height - 5, tag_text);
+ bar_draw_rect(bar_monitors[m].window, bar_sel_bg_color, x, 0, tagw, bar_height);
+ bar_draw_text(bar_monitors[m].window, bar_sel_accent_color, x + bar_padding, bar_height - 5, tag_text);
} else {
- bar_draw_text(bar_monitors[m].window, white, x + bar_padding, bar_height - 5, tag_text);
+ bar_draw_text(bar_monitors[m].window, bar_fg_color, x + bar_padding, bar_height - 5, tag_text);
}
x += tagw + bar_padding;
}
status_x = bar_width - bar_padding - bar_text_width(bar_status);
if (status_x < x + bar_padding)
status_x = x + bar_padding;
- bar_draw_text(bar_monitors[m].window, white, status_x, bar_height - 5, bar_status);
+ bar_draw_text(bar_monitors[m].window, bar_fg_color, status_x, bar_height - 5, bar_status);
title_x = x + bar_padding;
tw = bar_text_width(bar_title);
if (title_x + tw < status_x - bar_padding)
- bar_draw_text(bar_monitors[m].window, white, title_x, bar_height - 5, bar_title);
+ bar_draw_text(bar_monitors[m].window, bar_sel_fg_color, title_x, bar_height - 5, bar_title);
}
XFlush(bar_display);
}
@@ -255,6 +262,39 @@ bar_set_bottom(int is_bottom)
bar_reconfigure();
}
+static unsigned long
+bar_alloc_color(const char *color_name, unsigned long fallback)
+{
+ Colormap cmap;
+ XColor color;
+
+ if (bar_display == NULL || color_name == NULL || color_name[0] == '\0')
+ return fallback;
+ cmap = DefaultColormap(bar_display, bar_screen);
+ if (!XParseColor(bar_display, cmap, color_name, &color))
+ return fallback;
+ if (!XAllocColor(bar_display, cmap, &color))
+ return fallback;
+ return color.pixel;
+}
+
+void
+bar_set_colors(const char *fg, const char *bg, const char *sel_fg,
+ const char *sel_bg, const char *sel_accent)
+{
+ if (fg != NULL)
+ bar_fg_color = bar_alloc_color(fg, bar_fg_color);
+ if (bg != NULL)
+ bar_bg_color = bar_alloc_color(bg, bar_bg_color);
+ if (sel_fg != NULL)
+ bar_sel_fg_color = bar_alloc_color(sel_fg, bar_sel_fg_color);
+ if (sel_bg != NULL)
+ bar_sel_bg_color = bar_alloc_color(sel_bg, bar_sel_bg_color);
+ if (sel_accent != NULL)
+ bar_sel_accent_color = bar_alloc_color(sel_accent, bar_sel_accent_color);
+ bar_draw();
+}
+
void
bar_reconfigure(void)
{
diff --git a/extras/bar.h b/extras/bar.h
index 08f4392..f12da4b 100644
--- a/extras/bar.h
+++ b/extras/bar.h
@@ -9,6 +9,8 @@ void bar_set_tags(const int *tags, int count, int selected_tag);
void bar_set_title(const char *title);
void bar_set_margins(int margin_x, int margin_y);
void bar_set_bottom(int is_bottom);
+void bar_set_colors(const char *fg, const char *bg, const char *sel_fg,
+ const char *sel_bg, const char *sel_accent);
void bar_reconfigure(void);
void bar_draw(void);
void bar_cleanup(void);
diff --git a/wm.c b/wm.c
index 87647cd..4b98a9f 100644
--- a/wm.c
+++ b/wm.c
@@ -1,5 +1,7 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "extras/ewmh/ewmh.h"
#ifdef XINERAMA
@@ -19,6 +21,11 @@
#define cmd_bar_margin_x 5
#define cmd_bar_margin_y 6
#define cmd_reload 7
+#define cmd_bar_nf 8
+#define cmd_bar_nb 9
+#define cmd_bar_sf 10
+#define cmd_bar_sb 11
+#define cmd_bar_sa 12
#define num_workspaces 9
#define modifier_variants 4
@@ -27,6 +34,7 @@ static int window_workspace[max_windows], window_count, current_workspace;
static Atom net_wm_desktop_atom;
#ifdef BAR
static Atom wm_bar_margin_x_atom, wm_bar_margin_y_atom, wm_bar_bottom_atom;
+static Atom wm_bar_nf_atom, wm_bar_nb_atom, wm_bar_sf_atom, wm_bar_sb_atom, wm_bar_sa_atom;
static Atom net_wm_name_atom, utf8_string_atom;
#endif
static int is_root_child(Display *display, Window root_window, Window window);
@@ -231,6 +239,47 @@ write_root_int_property(Display *display, Window root_window, Atom atom, int val
XChangeProperty(display, root_window, atom, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&card, 1);
}
+
+static char *
+read_root_string_property(Display *display, Window root_window, Atom atom)
+{
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop_data;
+ char *out;
+
+ prop_data = NULL;
+ if (XGetWindowProperty(display, root_window, atom, 0, 256, False, XA_STRING,
+ &actual_type, &actual_format, &nitems, &bytes_after, &prop_data) != Success)
+ return NULL;
+ if (prop_data == NULL)
+ return NULL;
+ if (actual_type != XA_STRING || actual_format != 8 || nitems < 1) {
+ XFree(prop_data);
+ return NULL;
+ }
+ out = (char *)malloc(nitems + 1);
+ if (out == NULL) {
+ XFree(prop_data);
+ return NULL;
+ }
+ memcpy(out, prop_data, nitems);
+ out[nitems] = '\0';
+ XFree(prop_data);
+ return out;
+}
+
+static void
+write_root_string_property(Display *display, Window root_window, Atom atom, const char *value)
+{
+ if (value == NULL || value[0] == '\0') {
+ XDeleteProperty(display, root_window, atom);
+ return;
+ }
+ XChangeProperty(display, root_window, atom, XA_STRING, 8, PropModeReplace,
+ (unsigned char *)value, (int)strlen(value));
+}
#endif
static void
@@ -379,6 +428,11 @@ main(int argc, char **argv)
wm_bar_margin_x_atom = XInternAtom(display, "_WM_BAR_MARGIN_X", False);
wm_bar_margin_y_atom = XInternAtom(display, "_WM_BAR_MARGIN_Y", False);
wm_bar_bottom_atom = XInternAtom(display, "_WM_BAR_BOTTOM", False);
+ wm_bar_nf_atom = XInternAtom(display, "_WM_BAR_NF", False);
+ wm_bar_nb_atom = XInternAtom(display, "_WM_BAR_NB", False);
+ wm_bar_sf_atom = XInternAtom(display, "_WM_BAR_SF", False);
+ wm_bar_sb_atom = XInternAtom(display, "_WM_BAR_SB", False);
+ wm_bar_sa_atom = XInternAtom(display, "_WM_BAR_SA", False);
net_wm_name_atom = XInternAtom(display, "_NET_WM_NAME", False);
utf8_string_atom = XInternAtom(display, "UTF8_STRING", False);
#endif
@@ -391,6 +445,21 @@ main(int argc, char **argv)
ewmh_sync(display, root_window, windows, window_workspace, window_count);
#ifdef BAR
bar_init(display, root_window);
+ {
+ char *nf, *nb, *sf, *sb, *sa;
+
+ nf = read_root_string_property(display, root_window, wm_bar_nf_atom);
+ nb = read_root_string_property(display, root_window, wm_bar_nb_atom);
+ sf = read_root_string_property(display, root_window, wm_bar_sf_atom);
+ sb = read_root_string_property(display, root_window, wm_bar_sb_atom);
+ sa = read_root_string_property(display, root_window, wm_bar_sa_atom);
+ bar_set_colors(nf, nb, sf, sb, sa);
+ free(nf);
+ free(nb);
+ free(sf);
+ free(sb);
+ free(sa);
+ }
bar_set_margins(read_root_int_property(display, root_window, wm_bar_margin_x_atom, 0),
read_root_int_property(display, root_window, wm_bar_margin_y_atom, 0));
bar_set_bottom(read_root_int_property(display, root_window, wm_bar_bottom_atom, 0) ? 1 : 0);
@@ -429,6 +498,43 @@ main(int argc, char **argv)
write_root_int_property(display, root_window, wm_bar_margin_y_atom, value);
refresh_bar(display);
continue;
+ } else if (command == cmd_bar_nf || command == cmd_bar_nb ||
+ command == cmd_bar_sf || command == cmd_bar_sb || command == cmd_bar_sa) {
+ Atom source_atom;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop_data;
+
+ source_atom = (Atom)event.xclient.data.l[1];
+ prop_data = NULL;
+ if (XGetWindowProperty(display, root_window, source_atom, 0, 256, False,
+ XA_STRING, &actual_type, &actual_format, &nitems, &bytes_after,
+ &prop_data) == Success &&
+ prop_data != NULL && actual_type == XA_STRING &&
+ actual_format == 8 && nitems > 0) {
+ if (command == cmd_bar_nf) {
+ bar_set_colors((char *)prop_data, NULL, NULL, NULL, NULL);
+ write_root_string_property(display, root_window, wm_bar_nf_atom, (char *)prop_data);
+ } else if (command == cmd_bar_nb) {
+ bar_set_colors(NULL, (char *)prop_data, NULL, NULL, NULL);
+ write_root_string_property(display, root_window, wm_bar_nb_atom, (char *)prop_data);
+ } else if (command == cmd_bar_sf) {
+ bar_set_colors(NULL, NULL, (char *)prop_data, NULL, NULL);
+ write_root_string_property(display, root_window, wm_bar_sf_atom, (char *)prop_data);
+ } else if (command == cmd_bar_sb) {
+ bar_set_colors(NULL, NULL, NULL, (char *)prop_data, NULL);
+ write_root_string_property(display, root_window, wm_bar_sb_atom, (char *)prop_data);
+ } else if (command == cmd_bar_sa) {
+ bar_set_colors(NULL, NULL, NULL, NULL, (char *)prop_data);
+ write_root_string_property(display, root_window, wm_bar_sa_atom, (char *)prop_data);
+ }
+ refresh_bar(display);
+ }
+ if (prop_data != NULL)
+ XFree(prop_data);
+ XDeleteProperty(display, root_window, source_atom);
+ continue;
}
#endif
if (command == cmd_kill) {
diff --git a/wmc.c b/wmc.c
index ab18a9d..415def1 100644
--- a/wmc.c
+++ b/wmc.c
@@ -1,4 +1,5 @@
#include <X11/Xlib.h>
+#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
@@ -11,6 +12,11 @@
#define cmd_bar_margin_x 5
#define cmd_bar_margin_y 6
#define cmd_reload 7
+#define cmd_bar_nf 8
+#define cmd_bar_nb 9
+#define cmd_bar_sf 10
+#define cmd_bar_sb 11
+#define cmd_bar_sa 12
int
main(int argc, char **argv)
@@ -41,6 +47,19 @@ main(int argc, char **argv)
return 1;
}
} else if (argc == 4 && !strcmp(argv[1], "bar")) {
+ if (!strcmp(argv[2], "nf"))
+ command = cmd_bar_nf;
+ else if (!strcmp(argv[2], "nb"))
+ command = cmd_bar_nb;
+ else if (!strcmp(argv[2], "sf"))
+ command = cmd_bar_sf;
+ else if (!strcmp(argv[2], "sb"))
+ command = cmd_bar_sb;
+ else if (!strcmp(argv[2], "sa"))
+ command = cmd_bar_sa;
+ if (command >= cmd_bar_nf && command <= cmd_bar_sa) {
+ value = 0;
+ } else {
value = (int)strtol(argv[3], &end_ptr, 10);
if (*end_ptr != '\0' || value < 0)
return 1;
@@ -49,9 +68,11 @@ main(int argc, char **argv)
else if (!strcmp(argv[2], "my"))
command = cmd_bar_margin_y;
else {
- fprintf(stderr, "usage: wmc bar mx <px> | wmc bar my <px>\n");
+ fprintf(stderr, "usage: wmc bar mx <px> | wmc bar my <px> | "
+ "wmc bar nf|nb|sf|sb|sa <color>\n");
return 1;
}
+ }
}
else if (argc == 2)
workspace = (int)strtol(argv[1], &end_ptr, 10);
@@ -62,7 +83,8 @@ main(int argc, char **argv)
workspace = (int)strtol(argv[2], &end_ptr, 10);
else {
fprintf(stderr, "usage: wmc [ws] 1-9 | wmc move 1-9 | wmc kill | wmc reload | "
- "wmc bar top|bottom | wmc bar mx <px> | wmc bar my <px>\n");
+ "wmc bar top|bottom | wmc bar mx <px> | wmc bar my <px> | "
+ "wmc bar nf|nb|sf|sb|sa <color>\n");
return 1;
}
if ((command == cmd_workspace || command == cmd_move) &&
@@ -83,6 +105,18 @@ main(int argc, char **argv)
event.xclient.data.l[0] = command;
if (command == cmd_workspace || command == cmd_move)
event.xclient.data.l[1] = workspace > 0 ? workspace - 1 : 0;
+ else if (command >= cmd_bar_nf && command <= cmd_bar_sa) {
+ Atom payload_atom;
+ char atom_name[64];
+ static unsigned long seq;
+
+ seq++;
+ snprintf(atom_name, sizeof(atom_name), "_WM_CTL_PAYLOAD_%lu", seq);
+ payload_atom = XInternAtom(display, atom_name, False);
+ XChangeProperty(display, root_window, payload_atom, XA_STRING, 8, PropModeReplace,
+ (unsigned char *)argv[3], (int)strlen(argv[3]));
+ event.xclient.data.l[1] = (long)payload_atom;
+ }
else
event.xclient.data.l[1] = workspace;
XSendEvent(display, root_window, False, SubstructureNotifyMask, &event);