diff
Makefile | 6 ++
config.mk | 1 +
extras/bar.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
extras/bar.h | 16 +++
extras/xinerama.c | 16 +++
extras/xinerama.h | 1 +
wm.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++-
wmc.c | 47 ++++++++-
8 files changed, 616 insertions(+), 9 deletions(-)
diff --git a/Makefile b/Makefile
index 894efed..8cafd27 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,12 @@ endif
ifeq ($(XINERAMA),1)
WM_EXTRAS += extras/xinerama.c
LDLIBS += -lXinerama
+CPPFLAGS += -DXINERAMA
+endif
+
+ifeq ($(BAR),1)
+WM_EXTRAS += extras/bar.c
+CPPFLAGS += -DBAR
endif
all: wm wmc
diff --git a/config.mk b/config.mk
index 969824a..908d91d 100644
--- a/config.mk
+++ b/config.mk
@@ -1,6 +1,7 @@
# features
EWMH=1
XINERAMA=1
+BAR=1
# uncomment on obsd and other systems which use the X11R6 path.
#CPPFLAGS += -I/usr/X11R6/include
diff --git a/extras/bar.c b/extras/bar.c
new file mode 100644
index 0000000..a966298
--- /dev/null
+++ b/extras/bar.c
@@ -0,0 +1,284 @@
+#include <X11/Xlib.h>
+#ifdef XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#define bar_height 18
+#define bar_padding 6
+#define max_status_len 512
+#define max_title_len 512
+#define max_tags 9
+#define max_monitors 16
+
+struct bar_monitor {
+ Window window;
+ int x;
+ int y;
+ int width;
+ int height;
+ int bar_width;
+};
+
+static Display *bar_display;
+static Window bar_root;
+static GC bar_gc;
+static XFontStruct *bar_font;
+static int bar_screen;
+static int bar_selected_tag;
+static int bar_tag_count;
+static int bar_monitor_count;
+static int bar_margin_x;
+static int bar_margin_y;
+static int bar_is_bottom;
+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 int
+bar_text_width(const char *text)
+{
+ if (bar_font == NULL || text == NULL)
+ return 0;
+ return XTextWidth(bar_font, text, (int)strlen(text));
+}
+
+static void
+bar_draw_rect(Window window, unsigned long color, int x, int y, int width, int height)
+{
+ XSetForeground(bar_display, bar_gc, color);
+ XFillRectangle(bar_display, window, bar_gc,
+ x, y, (unsigned int)width, (unsigned int)height);
+}
+
+static void
+bar_draw_text(Window window, unsigned long fg, int x, int y, const char *text)
+{
+ XSetForeground(bar_display, bar_gc, fg);
+ XDrawString(bar_display, window, bar_gc, x, y, text, (int)strlen(text));
+}
+
+static void
+bar_destroy_windows(void)
+{
+ int i;
+
+ for (i = 0; i < bar_monitor_count; i++) {
+ if (bar_monitors[i].window != None)
+ XDestroyWindow(bar_display, bar_monitors[i].window);
+ bar_monitors[i].window = None;
+ }
+ bar_monitor_count = 0;
+}
+
+static int
+bar_load_monitors(void)
+{
+ XWindowAttributes root_attrs;
+
+ if (!XGetWindowAttributes(bar_display, bar_root, &root_attrs))
+ return 0;
+ bar_monitor_count = 1;
+ bar_monitors[0].x = 0;
+ bar_monitors[0].y = 0;
+ bar_monitors[0].width = root_attrs.width;
+ bar_monitors[0].height = root_attrs.height;
+#ifdef XINERAMA
+ {
+ XineramaScreenInfo *screen_info;
+ int j, major, minor;
+ int i;
+
+ if (XineramaQueryExtension(bar_display, &major, &minor) &&
+ XineramaIsActive(bar_display)) {
+ screen_info = XineramaQueryScreens(bar_display, &j);
+ if (screen_info != None && j > 0) {
+ bar_monitor_count = j;
+ if (bar_monitor_count > max_monitors)
+ bar_monitor_count = max_monitors;
+ for (i = 0; i < bar_monitor_count; i++) {
+ bar_monitors[i].x = screen_info[i].x_org;
+ bar_monitors[i].y = screen_info[i].y_org;
+ bar_monitors[i].width = screen_info[i].width;
+ bar_monitors[i].height = screen_info[i].height;
+ }
+ XFree(screen_info);
+ }
+ }
+ }
+#endif
+ return bar_monitor_count;
+}
+
+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.event_mask = ExposureMask;
+ for (i = 0; i < bar_monitor_count; i++) {
+ window_x = bar_monitors[i].x + bar_margin_x;
+ window_y = bar_monitors[i].y + bar_margin_y;
+ window_width = bar_monitors[i].width - (bar_margin_x * 2);
+ if (window_width < 1)
+ window_width = 1;
+ if (bar_is_bottom)
+ window_y = bar_monitors[i].y + bar_monitors[i].height - bar_height - bar_margin_y;
+ if (window_y < bar_monitors[i].y)
+ window_y = bar_monitors[i].y;
+ bar_monitors[i].bar_width = window_width;
+ bar_monitors[i].window = XCreateWindow(bar_display, bar_root,
+ window_x, window_y, (unsigned int)window_width, bar_height, 0,
+ DefaultDepth(bar_display, bar_screen), CopyFromParent,
+ DefaultVisual(bar_display, bar_screen),
+ CWOverrideRedirect | CWBackPixel | CWEventMask, &attrs);
+ XMapRaised(bar_display, bar_monitors[i].window);
+ }
+}
+
+int
+bar_init(Display *display, Window root_window)
+{
+ bar_display = display;
+ bar_root = root_window;
+ bar_screen = DefaultScreen(display);
+ bar_font = XLoadQueryFont(display, "fixed");
+ if (bar_font == NULL)
+ return 0;
+ bar_gc = XCreateGC(display, root_window, 0, NULL);
+ XSetFont(display, bar_gc, bar_font->fid);
+ if (!bar_load_monitors())
+ return 0;
+ bar_create_windows();
+ XFlush(display);
+ return 1;
+}
+
+void
+bar_set_status(const char *status)
+{
+ if (status == NULL)
+ status = "";
+ snprintf(bar_status, sizeof(bar_status), "%s", status);
+}
+
+void
+bar_set_tags(const int *tags, int count, int selected_tag)
+{
+ int i;
+
+ bar_tag_count = count > max_tags ? max_tags : count;
+ bar_selected_tag = selected_tag;
+ for (i = 0; i < bar_tag_count; i++)
+ bar_tags[i] = tags[i];
+}
+
+void
+bar_set_title(const char *title)
+{
+ if (title == NULL)
+ title = "";
+ snprintf(bar_title, sizeof(bar_title), "%s", 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);
+ 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);
+ } else {
+ bar_draw_text(bar_monitors[m].window, white, 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);
+ 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);
+ }
+ XFlush(bar_display);
+}
+
+void
+bar_set_margins(int margin_x, int margin_y)
+{
+ if (margin_x < 0)
+ margin_x = bar_margin_x;
+ if (margin_y < 0)
+ margin_y = bar_margin_y;
+ if (margin_x < 0)
+ margin_x = 0;
+ if (margin_y < 0)
+ margin_y = 0;
+ bar_margin_x = margin_x;
+ bar_margin_y = margin_y;
+ bar_reconfigure();
+}
+
+void
+bar_set_bottom(int is_bottom)
+{
+ bar_is_bottom = is_bottom ? 1 : 0;
+ bar_reconfigure();
+}
+
+void
+bar_reconfigure(void)
+{
+ if (bar_display == NULL)
+ return;
+ bar_destroy_windows();
+ if (!bar_load_monitors())
+ return;
+ bar_create_windows();
+ bar_draw();
+}
+
+void
+bar_cleanup(void)
+{
+ if (bar_display == NULL)
+ return;
+ bar_destroy_windows();
+ if (bar_gc != None)
+ XFreeGC(bar_display, bar_gc);
+ if (bar_font != NULL)
+ XFreeFont(bar_display, bar_font);
+ bar_gc = None;
+ bar_font = NULL;
+ bar_display = NULL;
+ bar_root = None;
+}
diff --git a/extras/bar.h b/extras/bar.h
new file mode 100644
index 0000000..08f4392
--- /dev/null
+++ b/extras/bar.h
@@ -0,0 +1,16 @@
+#ifndef BAR_H
+#define BAR_H
+
+#include <X11/Xlib.h>
+
+int bar_init(Display *display, Window root_window);
+void bar_set_status(const char *status);
+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_reconfigure(void);
+void bar_draw(void);
+void bar_cleanup(void);
+
+#endif
diff --git a/extras/xinerama.c b/extras/xinerama.c
index ba43c9a..4e9a676 100644
--- a/extras/xinerama.c
+++ b/extras/xinerama.c
@@ -84,3 +84,19 @@ xinerama_monitor_for_window(Display *display, Window root_window, Window window)
y = window_attrs.y + (window_attrs.height / 2);
return xinerama_monitor_for_point(x, y);
}
+
+int
+xinerama_monitor_geometry(int monitor, int *x, int *y, int *width, int *height)
+{
+ if (monitor < 0 || monitor >= monitor_count)
+ return 0;
+ if (x != NULL)
+ *x = monitors[monitor].x;
+ if (y != NULL)
+ *y = monitors[monitor].y;
+ if (width != NULL)
+ *width = monitors[monitor].width;
+ if (height != NULL)
+ *height = monitors[monitor].height;
+ return 1;
+}
diff --git a/extras/xinerama.h b/extras/xinerama.h
index 3241592..4396d0b 100644
--- a/extras/xinerama.h
+++ b/extras/xinerama.h
@@ -6,5 +6,6 @@
int xinerama_init(Display *display, Window root_window);
int xinerama_monitor_for_point(int x, int y);
int xinerama_monitor_for_window(Display *display, Window root_window, Window window);
+int xinerama_monitor_geometry(int monitor, int *x, int *y, int *width, int *height);
#endif
diff --git a/wm.c b/wm.c
index e219d03..d9453e0 100644
--- a/wm.c
+++ b/wm.c
@@ -1,5 +1,13 @@
#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <unistd.h>
#include "extras/ewmh/ewmh.h"
+#ifdef XINERAMA
+#include "extras/xinerama.h"
+#endif
+#ifdef BAR
+#include "extras/bar.h"
+#endif
#define max_val(a, b) ((a) > (b) ? (a) : (b))
#define mod_key Mod1Mask
@@ -7,13 +15,96 @@
#define cmd_workspace 1
#define cmd_move 2
#define cmd_kill 3
+#define cmd_bar_position 4
+#define cmd_bar_margin_x 5
+#define cmd_bar_margin_y 6
+#define cmd_reload 7
#define num_workspaces 9
#define modifier_variants 4
static Window windows[max_windows];
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;
+#endif
static int is_root_child(Display *display, Window root_window, Window window);
+static int
+find_window_index(Window window)
+{
+ int i;
+
+ for (i = 0; i < window_count; i++)
+ if (windows[i] == window)
+ return i;
+ return -1;
+}
+
+static void
+place_window_at_pointer(Display *display, Window root_window, Window window)
+{
+ Window root_return, child_return;
+ XWindowAttributes root_attrs;
+ XWindowAttributes window_attrs;
+ int root_x, root_y, window_x, window_y;
+ int area_x, area_y, area_width, area_height;
+ unsigned int mask;
+
+ if (!XQueryPointer(display, root_window, &root_return, &child_return,
+ &root_x, &root_y, &window_x, &window_y, &mask))
+ return;
+ if (!XGetWindowAttributes(display, root_window, &root_attrs))
+ return;
+ if (!XGetWindowAttributes(display, window, &window_attrs))
+ return;
+ area_x = 0;
+ area_y = 0;
+ area_width = root_attrs.width;
+ area_height = root_attrs.height;
+#ifdef XINERAMA
+ {
+ int monitor;
+
+ monitor = xinerama_monitor_for_point(root_x, root_y);
+ if (!xinerama_monitor_geometry(monitor, &area_x, &area_y, &area_width, &area_height)) {
+ area_x = 0;
+ area_y = 0;
+ area_width = root_attrs.width;
+ area_height = root_attrs.height;
+ }
+ }
+#endif
+ window_x = root_x - (window_attrs.width / 2);
+ window_y = root_y - (window_attrs.height / 2);
+ if (window_x < area_x)
+ window_x = area_x;
+ if (window_y < area_y)
+ window_y = area_y;
+ if (window_x + window_attrs.width > area_x + area_width)
+ window_x = area_x + area_width - window_attrs.width;
+ if (window_y + window_attrs.height > area_y + area_height)
+ window_y = area_y + area_height - window_attrs.height;
+ if (window_x < area_x)
+ window_x = area_x;
+ if (window_y < area_y)
+ window_y = area_y;
+ XMoveWindow(display, window, window_x, window_y);
+}
+
+#ifdef BAR
+static void
+refresh_bar(void)
+{
+ static int tags[num_workspaces] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ bar_set_tags(tags, num_workspaces, current_workspace);
+ bar_set_title("wm");
+ bar_set_status("");
+ bar_draw();
+}
+#endif
+
static int
x_error_handler(Display *display, XErrorEvent *error)
{
@@ -40,6 +131,71 @@ get_window_index(Window window)
return window_count++;
}
+static int
+get_window_desktop(Display *display, Window window)
+{
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop_data;
+ unsigned long desktop;
+
+ if (net_wm_desktop_atom == None)
+ return -1;
+ prop_data = NULL;
+ if (XGetWindowProperty(display, window, net_wm_desktop_atom, 0, 1, False,
+ XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after,
+ &prop_data) != Success)
+ return -1;
+ if (prop_data == NULL)
+ return -1;
+ if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1) {
+ XFree(prop_data);
+ return -1;
+ }
+ desktop = *((unsigned long *)prop_data);
+ XFree(prop_data);
+ if (desktop >= num_workspaces)
+ return -1;
+ return (int)desktop;
+}
+
+#ifdef BAR
+static int
+read_root_int_property(Display *display, Window root_window, Atom atom, int default_value)
+{
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop_data;
+ unsigned long value;
+
+ prop_data = NULL;
+ if (XGetWindowProperty(display, root_window, atom, 0, 1, False, XA_CARDINAL,
+ &actual_type, &actual_format, &nitems, &bytes_after, &prop_data) != Success)
+ return default_value;
+ if (prop_data == NULL)
+ return default_value;
+ if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1) {
+ XFree(prop_data);
+ return default_value;
+ }
+ value = *((unsigned long *)prop_data);
+ XFree(prop_data);
+ return (int)value;
+}
+
+static void
+write_root_int_property(Display *display, Window root_window, Atom atom, int value)
+{
+ unsigned long card;
+
+ card = (unsigned long)value;
+ XChangeProperty(display, root_window, atom, XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *)&card, 1);
+}
+#endif
+
static void
remove_window(Window window)
{
@@ -98,9 +254,16 @@ track_windows(Display *display, Window root_window)
int i, j;
if (XQueryTree(display, root_window, &root_return, &parent, &children, (unsigned int *)&j)) {
- for (i = 0; i < j; i++)
- if (is_managed_window(display, root_window, children[i]))
- get_window_index(children[i]);
+ for (i = 0; i < j; i++) {
+ int window_index, desktop;
+
+ if (!is_managed_window(display, root_window, children[i]))
+ continue;
+ window_index = get_window_index(children[i]);
+ desktop = get_window_desktop(display, children[i]);
+ if (window_index >= 0 && desktop >= 0)
+ window_workspace[window_index] = desktop;
+ }
if (children != None)
XFree(children);
}
@@ -145,7 +308,7 @@ show_workspace(Display *display, Window root_window)
}
int
-main(void)
+main(int argc, char **argv)
{
Display *display;
Window root_window;
@@ -160,16 +323,33 @@ main(void)
is_dragging = 0;
drag_window = None;
+ (void)argc;
if ((display = XOpenDisplay(NULL)) == NULL)
return 1;
XSetErrorHandler(x_error_handler);
root_window = DefaultRootWindow(display);
control_atom = XInternAtom(display, "_WM_CTL", False);
- XSelectInput(display, root_window, SubstructureNotifyMask);
+ net_wm_desktop_atom = XInternAtom(display, "_NET_WM_DESKTOP", False);
+#ifdef BAR
+ 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);
+#endif
+ XSelectInput(display, root_window, SubstructureNotifyMask | StructureNotifyMask);
track_windows(display, root_window);
+#ifdef XINERAMA
+ xinerama_init(display, root_window);
+#endif
ewmh_init(display, root_window);
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ bar_init(display, root_window);
+ 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);
+ refresh_bar();
+#endif
grab_button_variants(display, 1, 0, root_window, GrabModeSync);
grab_button_variants(display, 1, mod_key, root_window, GrabModeAsync);
@@ -179,14 +359,44 @@ main(void)
XNextEvent(display, &event);
if (event.type == ClientMessage && event.xclient.message_type == control_atom) {
int command;
+#ifdef BAR
+ int value;
+#endif
command = (int)event.xclient.data.l[0];
i = (int)event.xclient.data.l[1];
+
+#ifdef BAR
+ value = (int)event.xclient.data.l[1];
+ if (command == cmd_bar_position) {
+ bar_set_bottom(value ? 1 : 0);
+ write_root_int_property(display, root_window, wm_bar_bottom_atom, value ? 1 : 0);
+ refresh_bar();
+ continue;
+ } else if (command == cmd_bar_margin_x) {
+ bar_set_margins(value, -1);
+ write_root_int_property(display, root_window, wm_bar_margin_x_atom, value);
+ refresh_bar();
+ continue;
+ } else if (command == cmd_bar_margin_y) {
+ bar_set_margins(-1, value);
+ write_root_int_property(display, root_window, wm_bar_margin_y_atom, value);
+ refresh_bar();
+ continue;
+ }
+#endif
if (command == cmd_kill) {
XGetInputFocus(display, &focused_window, &j);
if (!is_root_child(display, root_window, focused_window))
continue;
XKillClient(display, focused_window);
+ } else if (command == cmd_reload) {
+#ifdef BAR
+ bar_cleanup();
+#endif
+ XCloseDisplay(display);
+ execvp(argv[0], argv);
+ return 1;
} else if (i >= 0 && i < num_workspaces) {
if (command == cmd_workspace && i != current_workspace) {
track_windows(display, root_window);
@@ -194,6 +404,9 @@ main(void)
show_workspace(display, root_window);
ewmh_set_current_desktop(display, root_window, current_workspace);
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ refresh_bar();
+#endif
} else if (command == cmd_move) {
XGetInputFocus(display, &focused_window, &j);
if (!is_root_child(display, root_window, focused_window))
@@ -205,12 +418,32 @@ main(void)
if (i != current_workspace)
XUnmapWindow(display, focused_window);
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ refresh_bar();
+#endif
}
}
}
} else if (event.type == DestroyNotify) {
remove_window(event.xdestroywindow.window);
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ refresh_bar();
+#endif
+ } else if (event.type == MapNotify) {
+ Window mapped_window;
+
+ mapped_window = event.xmap.window;
+ if (!is_managed_window(display, root_window, mapped_window))
+ continue;
+ if (find_window_index(mapped_window) < 0) {
+ place_window_at_pointer(display, root_window, mapped_window);
+ get_window_index(mapped_window);
+ ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ refresh_bar();
+#endif
+ }
} else if (event.type == ButtonPress && event.xbutton.subwindow != None) {
drag_window = event.xbutton.subwindow;
if (!is_managed_window(display, root_window, drag_window)) {
@@ -224,6 +457,9 @@ main(void)
if (j >= 0)
window_workspace[j] = current_workspace;
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+#ifdef BAR
+ refresh_bar();
+#endif
if (!(event.xbutton.state & mod_key) && event.xbutton.button == 1) {
XAllowEvents(display, ReplayPointer, event.xbutton.time);
continue;
@@ -260,6 +496,14 @@ main(void)
is_dragging = 0;
drag_window = None;
XUngrabPointer(display, CurrentTime);
+ } else if (event.type == ConfigureNotify &&
+ event.xconfigure.window == root_window) {
+#ifdef XINERAMA
+ xinerama_init(display, root_window);
+#endif
+#ifdef BAR
+ bar_reconfigure();
+#endif
}
}
}
diff --git a/wmc.c b/wmc.c
index 1ad063a..ab18a9d 100644
--- a/wmc.c
+++ b/wmc.c
@@ -7,6 +7,10 @@
#define cmd_workspace 1
#define cmd_move 2
#define cmd_kill 3
+#define cmd_bar_position 4
+#define cmd_bar_margin_x 5
+#define cmd_bar_margin_y 6
+#define cmd_reload 7
int
main(int argc, char **argv)
@@ -15,13 +19,40 @@ main(int argc, char **argv)
Window root_window;
XEvent event;
Atom control_atom;
- int command, workspace;
+ int command, workspace, value;
char *end_ptr;
command = cmd_workspace;
workspace = 0;
+ value = 0;
if (argc == 2 && !strcmp(argv[1], "kill"))
command = cmd_kill;
+ else if (argc == 2 && !strcmp(argv[1], "reload"))
+ command = cmd_reload;
+ else if (argc == 3 && !strcmp(argv[1], "bar")) {
+ if (!strcmp(argv[2], "top")) {
+ command = cmd_bar_position;
+ value = 0;
+ } else if (!strcmp(argv[2], "bottom")) {
+ command = cmd_bar_position;
+ value = 1;
+ } else {
+ fprintf(stderr, "usage: wmc bar top|bottom\n");
+ return 1;
+ }
+ } else if (argc == 4 && !strcmp(argv[1], "bar")) {
+ value = (int)strtol(argv[3], &end_ptr, 10);
+ if (*end_ptr != '\0' || value < 0)
+ return 1;
+ if (!strcmp(argv[2], "mx"))
+ command = cmd_bar_margin_x;
+ else if (!strcmp(argv[2], "my"))
+ command = cmd_bar_margin_y;
+ else {
+ fprintf(stderr, "usage: wmc bar mx <px> | wmc bar my <px>\n");
+ return 1;
+ }
+ }
else if (argc == 2)
workspace = (int)strtol(argv[1], &end_ptr, 10);
else if (argc == 3 && !strcmp(argv[1], "move")) {
@@ -30,11 +61,16 @@ main(int argc, char **argv)
} else if (argc == 3 && !strcmp(argv[1], "ws"))
workspace = (int)strtol(argv[2], &end_ptr, 10);
else {
- fprintf(stderr, "usage: wmc [ws] 1-9 | wmc move 1-9 | wmc kill\n");
+ 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");
return 1;
}
- if (command != cmd_kill && (*end_ptr != '\0' || workspace < 1 || workspace > 9))
+ if ((command == cmd_workspace || command == cmd_move) &&
+ (*end_ptr != '\0' || workspace < 1 || workspace > 9))
return 1;
+ if (command == cmd_bar_position || command == cmd_bar_margin_x ||
+ command == cmd_bar_margin_y)
+ workspace = value;
if ((display = XOpenDisplay(NULL)) == NULL)
return 1;
root_window = DefaultRootWindow(display);
@@ -45,7 +81,10 @@ main(int argc, char **argv)
event.xclient.message_type = control_atom;
event.xclient.format = 32;
event.xclient.data.l[0] = command;
- event.xclient.data.l[1] = workspace > 0 ? workspace - 1 : 0;
+ if (command == cmd_workspace || command == cmd_move)
+ event.xclient.data.l[1] = workspace > 0 ? workspace - 1 : 0;
+ else
+ event.xclient.data.l[1] = workspace;
XSendEvent(display, root_window, False, SubstructureNotifyMask, &event);
XFlush(display);
XCloseDisplay(display);