int border_width = 1;
int region_padding = 0;
int tile_gap = 0;
+int java_workaround = 1;
int verbose_layout = 0;
time_t time_started;
pid_t bar_pid;
_NET_CLIENT_LIST,
_NET_CLOSE_WINDOW,
_NET_CURRENT_DESKTOP,
+ _NET_DESKTOP_GEOMETRY,
_NET_DESKTOP_NAMES,
+ _NET_DESKTOP_VIEWPORT,
_NET_MOVERESIZE_WINDOW,
+ _NET_NUMBER_OF_DESKTOPS,
+ _NET_RESTACK_WINDOW,
_NET_WM_ACTION_ABOVE,
_NET_WM_ACTION_CLOSE,
_NET_WM_ACTION_FULLSCREEN,
_NET_WM_DESKTOP,
_NET_WM_FULL_PLACEMENT,
_NET_WM_NAME,
- _NET_NUMBER_OF_DESKTOPS,
_NET_WM_STATE,
_NET_WM_STATE_ABOVE,
_NET_WM_STATE_FULLSCREEN,
{"_NET_CLIENT_LIST", XCB_ATOM_NONE},
{"_NET_CLOSE_WINDOW", XCB_ATOM_NONE},
{"_NET_CURRENT_DESKTOP", XCB_ATOM_NONE},
+ {"_NET_DESKTOP_GEOMETRY", XCB_ATOM_NONE},
{"_NET_DESKTOP_NAMES", XCB_ATOM_NONE},
+ {"_NET_DESKTOP_VIEWPORT", XCB_ATOM_NONE},
{"_NET_MOVERESIZE_WINDOW", XCB_ATOM_NONE},
+ {"_NET_NUMBER_OF_DESKTOPS", XCB_ATOM_NONE},
+ {"_NET_RESTACK_WINDOW", XCB_ATOM_NONE},
{"_NET_WM_ACTION_ABOVE", XCB_ATOM_NONE},
{"_NET_WM_ACTION_CLOSE", XCB_ATOM_NONE},
{"_NET_WM_ACTION_FULLSCREEN", XCB_ATOM_NONE},
{"_NET_WM_DESKTOP", XCB_ATOM_NONE},
{"_NET_WM_FULL_PLACEMENT", XCB_ATOM_NONE},
{"_NET_WM_NAME", XCB_ATOM_NONE},
- {"_NET_NUMBER_OF_DESKTOPS", XCB_ATOM_NONE},
{"_NET_WM_STATE", XCB_ATOM_NONE},
{"_NET_WM_STATE_ABOVE", XCB_ATOM_NONE},
{"_NET_WM_STATE_FULLSCREEN", XCB_ATOM_NONE},
void ewmh_update_client_list(void);
void ewmh_update_current_desktop(void);
void ewmh_update_desktop_names(void);
+void ewmh_update_desktops(void);
void ewmh_change_wm_state(struct ws_win *, xcb_atom_t, long);
void ewmh_update_wm_state(struct ws_win *);
char *expand_tilde(const char *);
void win_to_ws(struct ws_win *, int, int);
pid_t window_get_pid(xcb_window_t);
void wkill(struct swm_region *, union arg *);
-void workaround(void);
void update_ws_stack(struct workspace *);
void xft_init(struct swm_region *);
void _add_startup_exception(const char *, va_list);
void
setup_ewmh(void)
{
+ xcb_window_t root, win;
int i, j, num_screens;
-
for (i = 0; i < LENGTH(ewmh); i++)
ewmh[i].atom = get_atom_from_string(ewmh[i].name);
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++) {
- /* Support check window will be created by workaround(). */
+ root = screens[i].root;
+
+ /* Set up _NET_SUPPORTING_WM_CHECK. */
+ win = xcb_generate_id(conn);
+ xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, root,
+ 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ XCB_COPY_FROM_PARENT, 0, NULL);
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
+ a_net_wm_check, XCB_ATOM_WINDOW, 32, 1, &win);
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win,
+ a_net_wm_check, XCB_ATOM_WINDOW, 32, 1, &win);
+
+ /*
+ * Impersonate LG3D non-reparenting WM, written by Sun, to
+ * workaround a Java GUI rendering issue.
+ */
+ if (java_workaround)
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win,
+ ewmh[_NET_WM_NAME].atom, a_utf8_string,
+ 8, strlen("LG3D"), "LG3D");
+ else
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win,
+ ewmh[_NET_WM_NAME].atom, a_utf8_string,
+ 8, strlen("spectrwm"), "spectrwm");
/* Report supported atoms */
- xcb_delete_property(conn, screens[i].root, a_net_supported);
+ xcb_delete_property(conn, root, a_net_supported);
for (j = 0; j < LENGTH(ewmh); j++)
- xcb_change_property(conn, XCB_PROP_MODE_APPEND,
- screens[i].root, a_net_supported, XCB_ATOM_ATOM,
- 32, 1, &ewmh[j].atom);
+ xcb_change_property(conn, XCB_PROP_MODE_APPEND, root,
+ a_net_supported, XCB_ATOM_ATOM, 32, 1,
+ &ewmh[j].atom);
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
- screens[i].root, ewmh[_NET_NUMBER_OF_DESKTOPS].atom,
- XCB_ATOM_CARDINAL, 32, 1, &workspace_limit);
}
+
+ ewmh_update_desktops();
+ ewmh_get_desktop_names();
}
void
set_region(struct swm_region *r)
{
struct swm_region *rf;
+ int vals[2];
if (r == NULL)
return;
rf = r->s->r_focus;
/* Unfocus old region bar. */
- if (rf) {
+ if (rf != NULL) {
if (rf == r)
return;
&r->s->c[SWM_S_COLOR_BAR_BORDER_UNFOCUS].pixel);
}
+ if (rf != NULL && rf != r && (X(rf) != X(r) || Y(rf) != Y(r) ||
+ WIDTH(rf) != WIDTH(r) || HEIGHT(rf) != HEIGHT(r))) {
+ /* Set _NET_DESKTOP_GEOMETRY. */
+ vals[0] = WIDTH(r);
+ vals[1] = HEIGHT(r);
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, r->s->root,
+ ewmh[_NET_DESKTOP_GEOMETRY].atom, XCB_ATOM_CARDINAL, 32, 2,
+ &vals);
+ }
+
/* Set region bar border to focus_color. */
xcb_change_window_attributes(conn, r->bar->id,
XCB_CW_BORDER_PIXEL, &r->s->c[SWM_S_COLOR_BAR_BORDER].pixel);
XCB_ATOM_CARDINAL, 32, 1, &screens[i].r_focus->ws->idx);
}
+void
+ewmh_update_desktops(void)
+{
+ int num_screens, i, j;
+ uint32_t *vals;
+
+ vals = calloc(sizeof(uint32_t), workspace_limit * 2);
+ if (vals == NULL)
+ err(1, "ewmh_update_desktops: calloc: failed to allocate "
+ "memory.");
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; i++) {
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_NUMBER_OF_DESKTOPS].atom,
+ XCB_ATOM_CARDINAL, 32, 1, &workspace_limit);
+
+ for (j = 0; j < workspace_limit; ++j) {
+ if (screens[i].ws[j].r != NULL) {
+ vals[j * 2] = X(screens[i].ws[j].r);
+ vals[j * 2 + 1] = Y(screens[i].ws[j].r);
+ } else if (screens[i].ws[j].old_r != NULL) {
+ vals[j * 2] = X(screens[i].ws[j].old_r);
+ vals[j * 2 + 1] = Y(screens[i].ws[j].old_r);
+ } else {
+ vals[j * 2] = vals[j * 2 + 1] = 0;
+ }
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_DESKTOP_VIEWPORT].atom,
+ XCB_ATOM_CARDINAL, 32, workspace_limit * 2, vals);
+ }
+
+ free(vals);
+}
+
void
search_resp_search_workspace(const char *resp)
{
SWM_S_WINDOW_CLASS_ENABLED,
SWM_S_WINDOW_INSTANCE_ENABLED,
SWM_S_WINDOW_NAME_ENABLED,
- SWM_S_WORKSPACE_LIMIT
+ SWM_S_WORKSPACE_LIMIT,
+ SWM_S_WORKSPACE_NAME,
};
int
{
struct workspace *ws;
int i, ws_id, num_screens;
- char *b, *str;
+ char *b, *str, s[1024];
switch (flags) {
case SWM_S_BAR_ACTION:
else if (workspace_limit < 1)
workspace_limit = 1;
+ ewmh_update_desktops();
+ break;
+ case SWM_S_WORKSPACE_NAME:
+ if (getenv("SWM_STARTED") != NULL)
+ return (0);
+
+ bzero(s, sizeof s);
+ if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2)
+ errx(1, "invalid entry, should be 'ws[<idx>]:name'");
+ ws_id--;
+ if (ws_id < 0 || ws_id >= workspace_limit)
+ errx(1, "setconfvalue: workspace_name: invalid "
+ "workspace %d.", ws_id + 1);
+
num_screens = get_screen_count();
- for (i = 0; i < num_screens; i++) {
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
- screens[i].root, ewmh[_NET_NUMBER_OF_DESKTOPS].atom,
- XCB_ATOM_CARDINAL, 32, 1, &workspace_limit);
+ for (i = 0; i < num_screens; ++i) {
+ ws = (struct workspace *)&screens[i].ws;
+
+ if (strlen(s) > 0) {
+ free(ws[ws_id].name);
+ if ((ws[ws_id].name = strdup(s)) == NULL)
+ err(1, "setconfvalue: workspace_name.");
+
+ ewmh_update_desktop_names();
+ ewmh_get_desktop_names();
+ }
}
break;
default:
{ "window_instance_enabled", setconfvalue, SWM_S_WINDOW_INSTANCE_ENABLED },
{ "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED },
{ "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT },
+ { "name", setconfvalue, SWM_S_WORKSPACE_NAME },
};
void
struct ws_win *win;
struct swm_region *r = NULL;
union arg a;
+ uint32_t val[2];
int num_screens, i;
xcb_map_request_event_t mre;
#ifdef SWM_DEBUG
HEIGHT(win) = e->data.data32[4];
update_window(win);
- }
- else {
+ } else {
/* TODO: Change stack sizes */
/* notify no change was made. */
config_win(win, NULL);
}
+ } else if (e->type == ewmh[_NET_RESTACK_WINDOW].atom) {
+ DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_RESTACK_WINDOW\n");
+ val[0] = e->data.data32[1]; /* Sibling window. */
+ val[1] = e->data.data32[2]; /* Stack mode detail. */
+
+ xcb_configure_window(conn, win->id, XCB_CONFIG_WINDOW_SIBLING |
+ XCB_CONFIG_WINDOW_STACK_MODE, val);
} else if (e->type == ewmh[_NET_WM_STATE].atom) {
DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_WM_STATE\n");
ewmh_change_wm_state(win, e->data.data32[1], e->data.data32[0]);
a_swm_ws = get_atom_from_string("_SWM_WS");
}
-void
-workaround(void)
-{
- int i, num_screens;
- xcb_window_t root, win;
-
- /* work around sun jdk bugs, code from wmname */
-
- num_screens = get_screen_count();
- for (i = 0; i < num_screens; i++) {
- root = screens[i].root;
-
- win = xcb_generate_id(conn);
- xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, root,
- 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
- XCB_COPY_FROM_PARENT, 0, NULL);
-
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
- a_net_wm_check, XCB_ATOM_WINDOW, 32, 1, &win);
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win,
- a_net_wm_check, XCB_ATOM_WINDOW, 32, 1, &win);
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win,
- ewmh[_NET_WM_NAME].atom, a_utf8_string, 8, strlen("LG3D"),
- "LG3D");
- }
-}
-
void
shutdown_cleanup(void)
{
validate_spawns();
- /* set some values to work around bad programs */
- workaround();
/* grab existing windows (before we build the bars) */
grab_windows();