* Emulates mkdir -p (creates any missing folders)
*
*/
-static bool mkdirp(const char *path) {
+bool mkdirp(const char *path) {
if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
return true;
if (errno != ENOENT) {
}
char *copy = sstrdup(path);
/* strip trailing slashes, if any */
- while (copy[strlen(copy)-1] == '/')
- copy[strlen(copy)-1] = '\0';
+ while (copy[strlen(copy) - 1] == '/')
+ copy[strlen(copy) - 1] = '\0';
char *sep = strrchr(copy, '/');
if (sep == NULL) {
if (!interested)
continue;
- ipc_send_message(current->fd, strlen(payload), message_type, (const uint8_t*)payload);
+ ipc_send_message(current->fd, strlen(payload), message_type, (const uint8_t *)payload);
}
}
/* To get a properly terminated buffer, we copy
* message_size bytes out of the buffer */
char *command = scalloc(message_size + 1);
- strncpy(command, (const char*)message, message_size);
+ strncpy(command, (const char *)message, message_size);
LOG("IPC: received: *%s*\n", command);
- struct CommandResult *command_output = parse_command((const char*)command);
+ yajl_gen gen = yajl_gen_alloc(NULL);
+
+ CommandResult *result = parse_command((const char *)command, gen);
free(command);
- if (command_output->needs_tree_render)
+ if (result->needs_tree_render)
tree_render();
+ command_result_free(result);
+
const unsigned char *reply;
ylength length;
- yajl_gen_get_buf(command_output->json_gen, &reply, &length);
+ yajl_gen_get_buf(gen, &reply, &length);
ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_COMMAND,
- (const uint8_t*)reply);
+ (const uint8_t *)reply);
- yajl_gen_free(command_output->json_gen);
+ yajl_gen_free(gen);
}
static void dump_rect(yajl_gen gen, const char *name, Rect r) {
y(map_close);
}
+static void dump_binding(yajl_gen gen, Binding *bind) {
+ y(map_open);
+ ystr("input_code");
+ y(integer, bind->keycode);
+
+ ystr("input_type");
+ ystr((const char *)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse"));
+
+ ystr("symbol");
+ if (bind->symbol == NULL)
+ y(null);
+ else
+ ystr(bind->symbol);
+
+ ystr("command");
+ ystr(bind->command);
+
+ ystr("mods");
+ y(array_open);
+ for (int i = 0; i < 8; i++) {
+ if (bind->mods & (1 << i)) {
+ switch (1 << i) {
+ case XCB_MOD_MASK_SHIFT:
+ ystr("shift");
+ break;
+ case XCB_MOD_MASK_LOCK:
+ ystr("lock");
+ break;
+ case XCB_MOD_MASK_CONTROL:
+ ystr("ctrl");
+ break;
+ case XCB_MOD_MASK_1:
+ ystr("Mod1");
+ break;
+ case XCB_MOD_MASK_2:
+ ystr("Mod2");
+ break;
+ case XCB_MOD_MASK_3:
+ ystr("Mod3");
+ break;
+ case XCB_MOD_MASK_4:
+ ystr("Mod4");
+ break;
+ case XCB_MOD_MASK_5:
+ ystr("Mod5");
+ break;
+ }
+ }
+ }
+ y(array_close);
+
+ y(map_close);
+}
+
void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
y(map_open);
ystr("id");
else {
if (con_orientation(con) == HORIZ)
ystr("horizontal");
- else ystr("vertical");
+ else
+ ystr("vertical");
}
ystr("scratchpad_state");
ystr("percent");
if (con->percent == 0.0)
y(null);
- else y(double, con->percent);
+ else
+ y(double, con->percent);
ystr("urgent");
y(bool, con->urgent);
y(integer, con->current_border_width);
dump_rect(gen, "rect", con->rect);
+ dump_rect(gen, "deco_rect", con->deco_rect);
dump_rect(gen, "window_rect", con->window_rect);
dump_rect(gen, "geometry", con->geometry);
ystr("name");
if (con->window && con->window->name)
ystr(i3string_as_utf8(con->window->name));
- else
+ else if (con->name != NULL)
ystr(con->name);
+ else
+ y(null);
if (con->type == CT_WORKSPACE) {
ystr("num");
ystr("window");
if (con->window)
y(integer, con->window->id);
- else y(null);
+ else
+ y(null);
if (con->window && !inplace_restart) {
/* Window properties are useless to preserve when restarting because
ystr("window_properties");
y(map_open);
-#define DUMP_PROPERTY(key, prop_name) do { \
- if (con->window->prop_name != NULL) { \
- ystr(key); \
- ystr(con->window->prop_name); \
- } \
-} while (0)
+#define DUMP_PROPERTY(key, prop_name) \
+ do { \
+ if (con->window->prop_name != NULL) { \
+ ystr(key); \
+ ystr(con->window->prop_name); \
+ } \
+ } while (0)
DUMP_PROPERTY("class", class_class);
DUMP_PROPERTY("instance", class_instance);
ystr(i3string_as_utf8(con->window->name));
}
+ ystr("transient_for");
+ if (con->window->transient_for == XCB_NONE)
+ y(null);
+ else
+ y(integer, con->window->transient_for);
+
y(map_close);
}
y(integer, match->insert_where);
}
-#define DUMP_REGEX(re_name) do { \
- if (match->re_name != NULL) { \
- ystr(# re_name); \
- ystr(match->re_name->pattern); \
- } \
-} while (0)
+#define DUMP_REGEX(re_name) \
+ do { \
+ if (match->re_name != NULL) { \
+ ystr(#re_name); \
+ ystr(match->re_name->pattern); \
+ } \
+ } while (0)
DUMP_REGEX(class);
DUMP_REGEX(instance);
y(array_close);
}
-#define YSTR_IF_SET(name) \
- do { \
- if (config->name) { \
- ystr( # name); \
+#define YSTR_IF_SET(name) \
+ do { \
+ if (config->name) { \
+ ystr(#name); \
ystr(config->name); \
- } \
+ } \
} while (0)
YSTR_IF_SET(tray_output);
case M_MOD3:
ystr("Mod3");
break;
- /*
+ /*
case M_MOD4:
ystr("Mod4");
break;
break;
}
+ if (config->wheel_up_cmd) {
+ ystr("wheel_up_cmd");
+ ystr(config->wheel_up_cmd);
+ }
+
+ if (config->wheel_down_cmd) {
+ ystr("wheel_down_cmd");
+ ystr(config->wheel_down_cmd);
+ }
+
ystr("position");
if (config->position == P_BOTTOM)
ystr("bottom");
- else ystr("top");
+ else
+ ystr("top");
YSTR_IF_SET(status_command);
YSTR_IF_SET(font);
y(bool, config->verbose);
#undef YSTR_IF_SET
-#define YSTR_IF_SET(name) \
- do { \
- if (config->colors.name) { \
- ystr( # name); \
+#define YSTR_IF_SET(name) \
+ do { \
+ if (config->colors.name) { \
+ ystr(#name); \
ystr(config->colors.name); \
- } \
+ } \
} while (0)
ystr("colors");
y(free);
}
-
/*
* Formats the reply message for a GET_WORKSPACES request and sends it to the
* client
y(map_open);
ystr("num");
- if (ws->num == -1)
- y(null);
- else y(integer, ws->num);
+ y(integer, ws->num);
ystr("name");
ystr(ws->name);
Con *ws = NULL;
if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT)))
ystr(ws->name);
- else y(null);
+ else
+ y(null);
y(map_close);
}
Con *con;
TAILQ_FOREACH(con, &all_cons, all_cons)
- if (con->mark != NULL)
- ystr(con->mark);
+ if (con->mark != NULL)
+ ystr(con->mark);
y(array_close);
/* To get a properly terminated buffer, we copy
* message_size bytes out of the buffer */
char *bar_id = scalloc(message_size + 1);
- strncpy(bar_id, (const char*)message, message_size);
+ strncpy(bar_id, (const char *)message, message_size);
LOG("IPC: looking for config for bar ID \"%s\"\n", bar_id);
Barconfig *current, *config = NULL;
TAILQ_FOREACH(current, &barconfigs, configs) {
int event = client->num_events;
client->num_events++;
- client->events = realloc(client->events, client->num_events * sizeof(char*));
+ client->events = realloc(client->events, client->num_events * sizeof(char *));
/* We copy the string because it is not null-terminated and strndup()
* is missing on some BSD systems */
- client->events[event] = scalloc(len+1);
+ client->events[event] = scalloc(len + 1);
memcpy(client->events[event], s, len);
DLOG("client is now subscribed to:\n");
.yajl_string = add_subscription,
};
- p = yalloc(&callbacks, (void*)client);
- stat = yajl_parse(p, (const unsigned char*)message, message_size);
+ p = yalloc(&callbacks, (void *)client);
+ stat = yajl_parse(p, (const unsigned char *)message, message_size);
if (stat != yajl_status_ok) {
unsigned char *err;
- err = yajl_get_error(p, true, (const unsigned char*)message,
+ err = yajl_get_error(p, true, (const unsigned char *)message,
message_size);
ELOG("YAJL parse error: %s\n", err);
yajl_free_error(p, err);
const char *reply = "{\"success\":false}";
- ipc_send_message(fd, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t*)reply);
+ ipc_send_message(fd, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t *)reply);
yajl_free(p);
return;
}
yajl_free(p);
const char *reply = "{\"success\":true}";
- ipc_send_message(fd, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t*)reply);
+ ipc_send_message(fd, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t *)reply);
}
/* The index of each callback function corresponds to the numeric
struct sockaddr_un peer;
socklen_t len = sizeof(struct sockaddr_un);
int client;
- if ((client = accept(w->fd, (struct sockaddr*)&peer, &len)) < 0) {
+ if ((client = accept(w->fd, (struct sockaddr *)&peer, &len)) < 0) {
if (errno == EINTR)
return;
- else perror("accept()");
+ else
+ perror("accept()");
return;
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_LOCAL;
strncpy(addr.sun_path, resolved, sizeof(addr.sun_path) - 1);
- if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0) {
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
perror("bind()");
free(resolved);
return -1;
}
/*
- * For the workspace "focus" event we send, along the usual "change" field,
- * also the current and previous workspace, in "current" and "old"
- * respectively.
+ * Generates a json workspace event. Returns a dynamically allocated yajl
+ * generator. Free with yajl_gen_free().
*/
-void ipc_send_workspace_focus_event(Con *current, Con *old) {
+yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old) {
setlocale(LC_NUMERIC, "C");
yajl_gen gen = ygenalloc();
y(map_open);
ystr("change");
- ystr("focus");
+ ystr(change);
ystr("current");
- dump_node(gen, current, false);
+ if (current == NULL)
+ y(null);
+ else
+ dump_node(gen, current, false);
ystr("old");
if (old == NULL)
y(map_close);
+ setlocale(LC_NUMERIC, "");
+
+ return gen;
+}
+
+/*
+ * For the workspace events we send, along with the usual "change" field, also
+ * the workspace container in "current". For focus events, we send the
+ * previously focused workspace in "old".
+ */
+void ipc_send_workspace_event(const char *change, Con *current, Con *old) {
+ yajl_gen gen = ipc_marshal_workspace_event(change, current, old);
+
const unsigned char *payload;
ylength length;
y(get_buf, &payload, &length);
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
+
y(free);
- setlocale(LC_NUMERIC, "");
}
/**
*/
void ipc_send_window_event(const char *property, Con *con) {
DLOG("Issue IPC window %s event (con = %p, window = 0x%08x)\n",
- property, con, (con->window ? con->window->id : XCB_WINDOW_NONE));
+ property, con, (con->window ? con->window->id : XCB_WINDOW_NONE));
setlocale(LC_NUMERIC, "C");
yajl_gen gen = ygenalloc();
y(free);
setlocale(LC_NUMERIC, "");
}
+
+/*
+ * For the binding events, we send the serialized binding struct.
+ */
+void ipc_send_binding_event(const char *event_type, Binding *bind) {
+ DLOG("Issue IPC binding %s event (sym = %s, code = %d)\n", event_type, bind->symbol, bind->keycode);
+
+ setlocale(LC_NUMERIC, "C");
+
+ yajl_gen gen = ygenalloc();
+
+ y(map_open);
+
+ ystr("change");
+ ystr(event_type);
+
+ ystr("binding");
+ dump_binding(gen, bind);
+
+ y(map_close);
+
+ const unsigned char *payload;
+ ylength length;
+ y(get_buf, &payload, &length);
+
+ ipc_send_event("binding", I3_IPC_EVENT_BINDING, (const char *)payload);
+
+ y(free);
+ setlocale(LC_NUMERIC, "");
+}