format **/*.c with clang-format-3.5
This has multiple effects: 1) The i3 codebase is now consistently formatted. clang-format uncovered plenty of places where inconsistent code made it into our code base. 2) When writing code, you don’t need to think or worry about our coding style. Write it in yours, then run clang-format-3.5 3) When submitting patches, we don’t need to argue about coding style. The basic idea is that we don’t want to care about _how_ we write the code, but _what_ it does :). The coding style that we use is defined in the .clang-format config file and is based on the google style, but adapted in such a way that the number of modifications to the i3 code base is minimal.
This commit is contained in:
parent
4d937b7dbb
commit
9200094203
@ -53,19 +53,21 @@
|
|||||||
#error "SYSCONFDIR not defined"
|
#error "SYSCONFDIR not defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FREE(pointer) do { \
|
#define FREE(pointer) \
|
||||||
if (pointer != NULL) { \
|
do { \
|
||||||
free(pointer); \
|
if (pointer != NULL) { \
|
||||||
pointer = NULL; \
|
free(pointer); \
|
||||||
} \
|
pointer = NULL; \
|
||||||
} \
|
} \
|
||||||
while (0)
|
} while (0)
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "libi3.h"
|
#include "libi3.h"
|
||||||
|
|
||||||
enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
|
enum { STEP_WELCOME,
|
||||||
enum { MOD_Mod1, MOD_Mod4 } modifier = MOD_Mod4;
|
STEP_GENERATE } current_step = STEP_WELCOME;
|
||||||
|
enum { MOD_Mod1,
|
||||||
|
MOD_Mod4 } modifier = MOD_Mod4;
|
||||||
|
|
||||||
static char *config_path;
|
static char *config_path;
|
||||||
static uint32_t xcb_numlock_mask;
|
static uint32_t xcb_numlock_mask;
|
||||||
@ -102,7 +104,6 @@ typedef struct tokenptr {
|
|||||||
int n;
|
int n;
|
||||||
} cmdp_token_ptr;
|
} cmdp_token_ptr;
|
||||||
|
|
||||||
|
|
||||||
#include "GENERATED_config_tokens.h"
|
#include "GENERATED_config_tokens.h"
|
||||||
|
|
||||||
static cmdp_state state;
|
static cmdp_state state;
|
||||||
@ -111,7 +112,7 @@ static cmdp_state state;
|
|||||||
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
||||||
* (likewise for other states, e.g. MODE or BAR).
|
* (likewise for other states, e.g. MODE or BAR).
|
||||||
* This list is used to process the nearest error token. */
|
* This list is used to process the nearest error token. */
|
||||||
static cmdp_state statelist[10] = { INITIAL };
|
static cmdp_state statelist[10] = {INITIAL};
|
||||||
/* NB: statelist_idx points to where the next entry will be inserted */
|
/* NB: statelist_idx points to where the next entry will be inserted */
|
||||||
static int statelist_idx = 1;
|
static int statelist_idx = 1;
|
||||||
|
|
||||||
@ -182,7 +183,6 @@ static void push_long(const char *identifier, long num) {
|
|||||||
"in the code, or a new command which contains more than "
|
"in the code, or a new command which contains more than "
|
||||||
"10 identified tokens.\n");
|
"10 identified tokens.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_string(const char *identifier) {
|
static const char *get_string(const char *identifier) {
|
||||||
@ -195,7 +195,6 @@ static const char *get_string(const char *identifier) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void clear_stack(void) {
|
static void clear_stack(void) {
|
||||||
for (int c = 0; c < 10; c++) {
|
for (int c = 0; c < 10; c++) {
|
||||||
if (stack[c].type == STACK_STR && stack[c].val.str != NULL)
|
if (stack[c].type == STACK_STR && stack[c].val.str != NULL)
|
||||||
@ -213,8 +212,8 @@ static void clear_stack(void) {
|
|||||||
*/
|
*/
|
||||||
static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
||||||
xcb_keycode_t i,
|
xcb_keycode_t i,
|
||||||
min_keycode = xcb_get_setup(conn)->min_keycode,
|
min_keycode = xcb_get_setup(conn)->min_keycode,
|
||||||
max_keycode = xcb_get_setup(conn)->max_keycode;
|
max_keycode = xcb_get_setup(conn)->max_keycode;
|
||||||
|
|
||||||
for (i = min_keycode; i && i <= max_keycode; i++) {
|
for (i = min_keycode; i && i <= max_keycode; i++) {
|
||||||
if (i == except_keycode)
|
if (i == except_keycode)
|
||||||
@ -228,7 +227,6 @@ static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *next_state(const cmdp_token *token) {
|
static char *next_state(const cmdp_token *token) {
|
||||||
cmdp_state _next_state = token->next_state;
|
cmdp_state _next_state = token->next_state;
|
||||||
|
|
||||||
@ -277,7 +275,7 @@ static char *next_state(const cmdp_token *token) {
|
|||||||
for (int i = 0; i < statelist_idx; i++) {
|
for (int i = 0; i < statelist_idx; i++) {
|
||||||
if (statelist[i] != _next_state)
|
if (statelist[i] != _next_state)
|
||||||
continue;
|
continue;
|
||||||
statelist_idx = i+1;
|
statelist_idx = i + 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +284,6 @@ static char *next_state(const cmdp_token *token) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *rewrite_binding(const char *input) {
|
static char *rewrite_binding(const char *input) {
|
||||||
state = INITIAL;
|
state = INITIAL;
|
||||||
statelist_idx = 1;
|
statelist_idx = 1;
|
||||||
@ -305,7 +302,7 @@ static char *rewrite_binding(const char *input) {
|
|||||||
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
|
|
||||||
//printf("remaining input: %s\n", walk);
|
//printf("remaining input: %s\n", walk);
|
||||||
|
|
||||||
cmdp_token_ptr *ptr = &(tokens[state]);
|
cmdp_token_ptr *ptr = &(tokens[state]);
|
||||||
for (c = 0; c < ptr->n; c++) {
|
for (c = 0; c < ptr->n; c++) {
|
||||||
@ -354,7 +351,7 @@ static char *rewrite_binding(const char *input) {
|
|||||||
if (*walk == '"') {
|
if (*walk == '"') {
|
||||||
beginning++;
|
beginning++;
|
||||||
walk++;
|
walk++;
|
||||||
while (*walk != '\0' && (*walk != '"' || *(walk-1) == '\\'))
|
while (*walk != '\0' && (*walk != '"' || *(walk - 1) == '\\'))
|
||||||
walk++;
|
walk++;
|
||||||
} else {
|
} else {
|
||||||
if (token->name[0] == 's') {
|
if (token->name[0] == 's') {
|
||||||
@ -366,22 +363,22 @@ static char *rewrite_binding(const char *input) {
|
|||||||
* semicolon (;). */
|
* semicolon (;). */
|
||||||
while (*walk != ' ' && *walk != '\t' &&
|
while (*walk != ' ' && *walk != '\t' &&
|
||||||
*walk != ']' && *walk != ',' &&
|
*walk != ']' && *walk != ',' &&
|
||||||
*walk != ';' && *walk != '\r' &&
|
*walk != ';' && *walk != '\r' &&
|
||||||
*walk != '\n' && *walk != '\0')
|
*walk != '\n' && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (walk != beginning) {
|
if (walk != beginning) {
|
||||||
char *str = scalloc(walk-beginning + 1);
|
char *str = scalloc(walk - beginning + 1);
|
||||||
/* We copy manually to handle escaping of characters. */
|
/* We copy manually to handle escaping of characters. */
|
||||||
int inpos, outpos;
|
int inpos, outpos;
|
||||||
for (inpos = 0, outpos = 0;
|
for (inpos = 0, outpos = 0;
|
||||||
inpos < (walk-beginning);
|
inpos < (walk - beginning);
|
||||||
inpos++, outpos++) {
|
inpos++, outpos++) {
|
||||||
/* We only handle escaped double quotes to not break
|
/* We only handle escaped double quotes to not break
|
||||||
* backwards compatibility with people using \w in
|
* backwards compatibility with people using \w in
|
||||||
* regular expressions etc. */
|
* regular expressions etc. */
|
||||||
if (beginning[inpos] == '\\' && beginning[inpos+1] == '"')
|
if (beginning[inpos] == '\\' && beginning[inpos + 1] == '"')
|
||||||
inpos++;
|
inpos++;
|
||||||
str[outpos] = beginning[inpos];
|
str[outpos] = beginning[inpos];
|
||||||
}
|
}
|
||||||
@ -410,15 +407,14 @@ static char *rewrite_binding(const char *input) {
|
|||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
walk++;
|
walk++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Having verboselog(), errorlog() and debuglog() is necessary when using libi3.
|
* Having verboselog(), errorlog() and debuglog() is necessary when using libi3.
|
||||||
*
|
*
|
||||||
@ -481,14 +477,14 @@ static char *resolve_tilde(const char *path) {
|
|||||||
static int handle_expose() {
|
static int handle_expose() {
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8};
|
xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8};
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#000000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
||||||
|
|
||||||
set_font(&font);
|
set_font(&font);
|
||||||
|
|
||||||
#define txt(x, row, text) \
|
#define txt(x, row, text) \
|
||||||
draw_text_ascii(text, pixmap, pixmap_gc,\
|
draw_text_ascii(text, pixmap, pixmap_gc, \
|
||||||
x, (row - 1) * font.height + 4, 300 - x * 2)
|
x, (row - 1) * font.height + 4, 300 - x * 2)
|
||||||
|
|
||||||
if (current_step == STEP_WELCOME) {
|
if (current_step == STEP_WELCOME) {
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
@ -521,14 +517,16 @@ static int handle_expose() {
|
|||||||
/* the not-selected modifier */
|
/* the not-selected modifier */
|
||||||
if (modifier == MOD_Mod4)
|
if (modifier == MOD_Mod4)
|
||||||
txt(31, 5, "<Alt>");
|
txt(31, 5, "<Alt>");
|
||||||
else txt(31, 4, "<Win>");
|
else
|
||||||
|
txt(31, 4, "<Win>");
|
||||||
|
|
||||||
/* the selected modifier */
|
/* the selected modifier */
|
||||||
set_font(&bold_font);
|
set_font(&bold_font);
|
||||||
set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000"));
|
set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000"));
|
||||||
if (modifier == MOD_Mod4)
|
if (modifier == MOD_Mod4)
|
||||||
txt(10, 4, "-> <Win>");
|
txt(10, 4, "-> <Win>");
|
||||||
else txt(10, 5, "-> <Alt>");
|
else
|
||||||
|
txt(10, 5, "-> <Alt>");
|
||||||
|
|
||||||
/* green */
|
/* green */
|
||||||
set_font(&font);
|
set_font(&font);
|
||||||
@ -565,16 +563,16 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
current_step = STEP_GENERATE;
|
current_step = STEP_GENERATE;
|
||||||
/* Set window title */
|
/* Set window title */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_NAME,
|
A__NET_WM_NAME,
|
||||||
A_UTF8_STRING,
|
A_UTF8_STRING,
|
||||||
8,
|
8,
|
||||||
strlen("i3: generate config"),
|
strlen("i3: generate config"),
|
||||||
"i3: generate config");
|
"i3: generate config");
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
}
|
} else
|
||||||
else finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cancel any time */
|
/* cancel any time */
|
||||||
@ -618,7 +616,7 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
* Handle button presses to make clicking on "<win>" and "<alt>" work
|
* Handle button presses to make clicking on "<win>" and "<alt>" work
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_button_press(xcb_button_press_event_t* event) {
|
static void handle_button_press(xcb_button_press_event_t *event) {
|
||||||
if (current_step != STEP_GENERATE)
|
if (current_step != STEP_GENERATE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -701,7 +699,8 @@ static void finish() {
|
|||||||
if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
|
if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
|
||||||
if (modifier == MOD_Mod1)
|
if (modifier == MOD_Mod1)
|
||||||
fputs("set $mod Mod1\n", ks_config);
|
fputs("set $mod Mod1\n", ks_config);
|
||||||
else fputs("set $mod Mod4\n", ks_config);
|
else
|
||||||
|
fputs("set $mod Mod4\n", ks_config);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,7 +728,7 @@ static void finish() {
|
|||||||
|
|
||||||
/* tell i3 to reload the config file */
|
/* tell i3 to reload the config file */
|
||||||
int sockfd = ipc_connect(socket_path);
|
int sockfd = ipc_connect(socket_path);
|
||||||
ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload");
|
ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t *)"reload");
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -750,8 +749,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"prefix", required_argument, 0, 'p'},
|
{"prefix", required_argument, 0, 'p'},
|
||||||
{"font", required_argument, 0, 'f'},
|
{"font", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:vh";
|
char *options_string = "s:vh";
|
||||||
|
|
||||||
@ -810,11 +808,11 @@ int main(int argc, char *argv[]) {
|
|||||||
modmap_cookie = xcb_get_modifier_mapping(conn);
|
modmap_cookie = xcb_get_modifier_mapping(conn);
|
||||||
symbols = xcb_key_symbols_alloc(conn);
|
symbols = xcb_key_symbols_alloc(conn);
|
||||||
|
|
||||||
/* Place requests for the atoms we need as soon as possible */
|
/* Place requests for the atoms we need as soon as possible */
|
||||||
#define xmacro(atom) \
|
#define xmacro(atom) \
|
||||||
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(conn, screen);
|
root_screen = xcb_aux_get_screen(conn, screen);
|
||||||
root = root_screen->root;
|
root = root_screen->root;
|
||||||
@ -832,54 +830,53 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
490, 297, 300, 205, /* dimensions */
|
490, 297, 300, 205, /* dimensions */
|
||||||
0, /* X11 border = 0, we draw our own */
|
0, /* X11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_PRESS});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define xmacro(name) \
|
#define xmacro(name) \
|
||||||
do { \
|
do { \
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
|
||||||
if (!reply) \
|
if (!reply) \
|
||||||
errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \
|
errx(EXIT_FAILURE, "Could not get atom " #name "\n"); \
|
||||||
\
|
\
|
||||||
A_ ## name = reply->atom; \
|
A_##name = reply->atom; \
|
||||||
free(reply); \
|
free(reply); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
/* Set dock mode */
|
/* Set dock mode */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_WINDOW_TYPE,
|
A__NET_WM_WINDOW_TYPE,
|
||||||
A_ATOM,
|
A_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG);
|
(unsigned char *)&A__NET_WM_WINDOW_TYPE_DIALOG);
|
||||||
|
|
||||||
/* Set window title */
|
/* Set window title */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_NAME,
|
A__NET_WM_NAME,
|
||||||
A_UTF8_STRING,
|
A_UTF8_STRING,
|
||||||
8,
|
8,
|
||||||
strlen("i3: first configuration"),
|
strlen("i3: first configuration"),
|
||||||
"i3: first configuration");
|
"i3: first configuration");
|
||||||
|
|
||||||
/* Create pixmap */
|
/* Create pixmap */
|
||||||
pixmap = xcb_generate_id(conn);
|
pixmap = xcb_generate_id(conn);
|
||||||
@ -922,13 +919,13 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
|
handle_key_press(NULL, conn, (xcb_key_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* TODO: handle mappingnotify */
|
/* TODO: handle mappingnotify */
|
||||||
|
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
handle_button_press((xcb_button_press_event_t*)event);
|
handle_button_press((xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
|
@ -29,11 +29,11 @@
|
|||||||
#include <i3/ipc.h>
|
#include <i3/ipc.h>
|
||||||
|
|
||||||
static uint32_t offset_next_write,
|
static uint32_t offset_next_write,
|
||||||
wrap_count;
|
wrap_count;
|
||||||
|
|
||||||
static i3_shmlog_header *header;
|
static i3_shmlog_header *header;
|
||||||
static char *logbuffer,
|
static char *logbuffer,
|
||||||
*walk;
|
*walk;
|
||||||
|
|
||||||
static int check_for_wrap(void) {
|
static int check_for_wrap(void) {
|
||||||
if (wrap_count == header->wrap_count)
|
if (wrap_count == header->wrap_count)
|
||||||
@ -70,8 +70,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"verbose", no_argument, 0, 'V'},
|
{"verbose", no_argument, 0, 'V'},
|
||||||
{"follow", no_argument, 0, 'f'},
|
{"follow", no_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:vfVh";
|
char *options_string = "s:vfVh";
|
||||||
|
|
||||||
@ -139,7 +138,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (logbuffer == MAP_FAILED)
|
if (logbuffer == MAP_FAILED)
|
||||||
err(EXIT_FAILURE, "Could not mmap SHM segment for the i3 log");
|
err(EXIT_FAILURE, "Could not mmap SHM segment for the i3 log");
|
||||||
|
|
||||||
header = (i3_shmlog_header*)logbuffer;
|
header = (i3_shmlog_header *)logbuffer;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("next_write = %d, last_wrap = %d, logbuffer_size = %d, shmname = %s\n",
|
printf("next_write = %d, last_wrap = %d, logbuffer_size = %d, shmname = %s\n",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -103,7 +103,7 @@ static void restore_input_focus(void) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static uint8_t *concat_strings(char **glyphs, int max) {
|
static uint8_t *concat_strings(char **glyphs, int max) {
|
||||||
uint8_t *output = calloc(max+1, 4);
|
uint8_t *output = calloc(max + 1, 4);
|
||||||
uint8_t *walk = output;
|
uint8_t *walk = output;
|
||||||
for (int c = 0; c < max; c++) {
|
for (int c = 0; c < max; c++) {
|
||||||
printf("at %c\n", glyphs[c][0]);
|
printf("at %c\n", glyphs[c][0]);
|
||||||
@ -112,7 +112,7 @@ static uint8_t *concat_strings(char **glyphs, int max) {
|
|||||||
memcpy(walk, glyphs[c], 2);
|
memcpy(walk, glyphs[c], 2);
|
||||||
walk += 2;
|
walk += 2;
|
||||||
} else {
|
} else {
|
||||||
strcpy((char*)walk, glyphs[c]);
|
strcpy((char *)walk, glyphs[c]);
|
||||||
walk += strlen(glyphs[c]);
|
walk += strlen(glyphs[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,9 +130,9 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t
|
|||||||
|
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4};
|
xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4};
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#FF0000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#000000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
||||||
|
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
@ -143,8 +143,7 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t
|
|||||||
draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492);
|
draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492);
|
||||||
}
|
}
|
||||||
/* … and the text */
|
/* … and the text */
|
||||||
if (input_position > 0)
|
if (input_position > 0) {
|
||||||
{
|
|
||||||
i3String *input = i3string_from_ucs2(glyphs_ucs, input_position);
|
i3String *input = i3string_from_ucs2(glyphs_ucs, input_position);
|
||||||
draw_text(input, pixmap, pixmap_gc, prompt_offset + 4, 4, 492);
|
draw_text(input, pixmap, pixmap_gc, prompt_offset + 4, 4, 492);
|
||||||
i3string_free(input);
|
i3string_free(input);
|
||||||
@ -174,14 +173,14 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void finish_input() {
|
static void finish_input() {
|
||||||
char *command = (char*)concat_strings(glyphs_utf8, input_position);
|
char *command = (char *)concat_strings(glyphs_utf8, input_position);
|
||||||
|
|
||||||
/* count the occurences of %s in the string */
|
/* count the occurences of %s in the string */
|
||||||
int c;
|
int c;
|
||||||
int len = strlen(format);
|
int len = strlen(format);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (c = 0; c < (len-1); c++)
|
for (c = 0; c < (len - 1); c++)
|
||||||
if (format[c] == '%' && format[c+1] == 's')
|
if (format[c] == '%' && format[c + 1] == 's')
|
||||||
cnt++;
|
cnt++;
|
||||||
printf("occurences = %d\n", cnt);
|
printf("occurences = %d\n", cnt);
|
||||||
|
|
||||||
@ -189,13 +188,13 @@ static void finish_input() {
|
|||||||
int inputlen = strlen(command);
|
int inputlen = strlen(command);
|
||||||
char *full = calloc(1,
|
char *full = calloc(1,
|
||||||
strlen(format) - (2 * cnt) /* format without all %s */
|
strlen(format) - (2 * cnt) /* format without all %s */
|
||||||
+ (inputlen * cnt) /* replaced %s */
|
+ (inputlen * cnt) /* replaced %s */
|
||||||
+ 1); /* trailing NUL */
|
+ 1); /* trailing NUL */
|
||||||
char *dest = full;
|
char *dest = full;
|
||||||
for (c = 0; c < len; c++) {
|
for (c = 0; c < len; c++) {
|
||||||
/* if this is not % or it is % but without a following 's',
|
/* if this is not % or it is % but without a following 's',
|
||||||
* just copy the character */
|
* just copy the character */
|
||||||
if (format[c] != '%' || (c == (len-1)) || format[c+1] != 's')
|
if (format[c] != '%' || (c == (len - 1)) || format[c + 1] != 's')
|
||||||
*(dest++) = format[c];
|
*(dest++) = format[c];
|
||||||
else {
|
else {
|
||||||
strncat(dest, command, inputlen);
|
strncat(dest, command, inputlen);
|
||||||
@ -212,7 +211,7 @@ static void finish_input() {
|
|||||||
|
|
||||||
xcb_aux_sync(conn);
|
xcb_aux_sync(conn);
|
||||||
|
|
||||||
ipc_send_message(sockfd, strlen(full), 0, (uint8_t*)full);
|
ipc_send_message(sockfd, strlen(full), 0, (uint8_t *)full);
|
||||||
|
|
||||||
free(full);
|
free(full);
|
||||||
|
|
||||||
@ -292,8 +291,8 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_char2b_t inp;
|
xcb_char2b_t inp;
|
||||||
inp.byte1 = ( ucs & 0xff00 ) >> 2;
|
inp.byte1 = (ucs & 0xff00) >> 2;
|
||||||
inp.byte2 = ( ucs & 0x00ff ) >> 0;
|
inp.byte2 = (ucs & 0x00ff) >> 0;
|
||||||
|
|
||||||
printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2);
|
printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2);
|
||||||
/* convert it to UTF-8 */
|
/* convert it to UTF-8 */
|
||||||
@ -326,8 +325,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"format", required_argument, 0, 'F'},
|
{"format", required_argument, 0, 'F'},
|
||||||
{"font", required_argument, 0, 'f'},
|
{"font", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:p:P:f:l:F:vh";
|
char *options_string = "s:p:P:f:l:F:vh";
|
||||||
|
|
||||||
@ -405,18 +403,17 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
50, 50, 500, font.height + 8, /* dimensions */
|
50, 50, 500, font.height + 8, /* dimensions */
|
||||||
0, /* X11 border = 0, we draw our own */
|
0, /* X11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
1, /* override redirect: don’t manage this window */
|
1, /* override redirect: don’t manage this window */
|
||||||
XCB_EVENT_MASK_EXPOSURE
|
XCB_EVENT_MASK_EXPOSURE});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
@ -467,15 +464,15 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
|
handle_key_press(NULL, conn, (xcb_key_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_KEY_RELEASE:
|
case XCB_KEY_RELEASE:
|
||||||
handle_key_release(NULL, conn, (xcb_key_release_event_t*)event);
|
handle_key_release(NULL, conn, (xcb_key_release_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
handle_expose(NULL, conn, (xcb_expose_event_t*)event);
|
handle_expose(NULL, conn, (xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,14 +78,15 @@ static int reply_boolean_cb(void *params, int val) {
|
|||||||
|
|
||||||
static int reply_string_cb(void *params, const unsigned char *val, size_t len) {
|
static int reply_string_cb(void *params, const unsigned char *val, size_t len) {
|
||||||
char *str = scalloc(len + 1);
|
char *str = scalloc(len + 1);
|
||||||
strncpy(str, (const char*)val, len);
|
strncpy(str, (const char *)val, len);
|
||||||
if (strcmp(last_key, "error") == 0)
|
if (strcmp(last_key, "error") == 0)
|
||||||
last_reply.error = str;
|
last_reply.error = str;
|
||||||
else if (strcmp(last_key, "input") == 0)
|
else if (strcmp(last_key, "input") == 0)
|
||||||
last_reply.input = str;
|
last_reply.input = str;
|
||||||
else if (strcmp(last_key, "errorposition") == 0)
|
else if (strcmp(last_key, "errorposition") == 0)
|
||||||
last_reply.errorposition = str;
|
last_reply.errorposition = str;
|
||||||
else free(str);
|
else
|
||||||
|
free(str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,11 +103,10 @@ static int reply_end_map_cb(void *params) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int reply_map_key_cb(void *params, const unsigned char *keyVal, size_t keyLen) {
|
static int reply_map_key_cb(void *params, const unsigned char *keyVal, size_t keyLen) {
|
||||||
free(last_key);
|
free(last_key);
|
||||||
last_key = scalloc(keyLen + 1);
|
last_key = scalloc(keyLen + 1);
|
||||||
strncpy(last_key, (const char*)keyVal, keyLen);
|
strncpy(last_key, (const char *)keyVal, keyLen);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +131,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
{"quiet", no_argument, 0, 'q'},
|
{"quiet", no_argument, 0, 'q'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:t:vhq";
|
char *options_string = "s:t:vhq";
|
||||||
|
|
||||||
@ -207,10 +206,10 @@ int main(int argc, char *argv[]) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
err(EXIT_FAILURE, "Could not connect to i3 on socket \"%s\"", socket_path);
|
err(EXIT_FAILURE, "Could not connect to i3 on socket \"%s\"", socket_path);
|
||||||
|
|
||||||
if (ipc_send_message(sockfd, strlen(payload), message_type, (uint8_t*)payload) == -1)
|
if (ipc_send_message(sockfd, strlen(payload), message_type, (uint8_t *)payload) == -1)
|
||||||
err(EXIT_FAILURE, "IPC: write()");
|
err(EXIT_FAILURE, "IPC: write()");
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
@ -232,7 +231,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) {
|
if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) {
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
handle = yajl_alloc(&reply_callbacks, NULL, NULL);
|
handle = yajl_alloc(&reply_callbacks, NULL, NULL);
|
||||||
yajl_status state = yajl_parse(handle, (const unsigned char*)reply, reply_length);
|
yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
|
154
i3-nagbar/main.c
154
i3-nagbar/main.c
@ -43,7 +43,7 @@ typedef struct {
|
|||||||
static xcb_window_t win;
|
static xcb_window_t win;
|
||||||
static xcb_pixmap_t pixmap;
|
static xcb_pixmap_t pixmap;
|
||||||
static xcb_gcontext_t pixmap_gc;
|
static xcb_gcontext_t pixmap_gc;
|
||||||
static xcb_rectangle_t rect = { 0, 0, 600, 20 };
|
static xcb_rectangle_t rect = {0, 0, 600, 20};
|
||||||
static i3Font font;
|
static i3Font font;
|
||||||
static i3String *prompt;
|
static i3String *prompt;
|
||||||
static button_t *buttons;
|
static button_t *buttons;
|
||||||
@ -100,7 +100,7 @@ static void start_application(const char *command) {
|
|||||||
setsid();
|
setsid();
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
/* This is the child */
|
/* This is the child */
|
||||||
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void*)NULL);
|
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void *)NULL);
|
||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -118,7 +118,7 @@ static button_t *get_button_at(int16_t x, int16_t y) {
|
|||||||
|
|
||||||
static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
|
static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
|
||||||
printf("button pressed on x = %d, y = %d\n",
|
printf("button pressed on x = %d, y = %d\n",
|
||||||
event->event_x, event->event_y);
|
event->event_x, event->event_y);
|
||||||
/* TODO: set a flag for the button, re-render */
|
/* TODO: set a flag for the button, re-render */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t
|
|||||||
*/
|
*/
|
||||||
static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
|
static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
|
||||||
printf("button released on x = %d, y = %d\n",
|
printf("button released on x = %d, y = %d\n",
|
||||||
event->event_x, event->event_y);
|
event->event_x, event->event_y);
|
||||||
/* If the user hits the close button, we exit(0) */
|
/* If the user hits the close button, we exit(0) */
|
||||||
if (event->event_x >= (rect.width - 32))
|
if (event->event_x >= (rect.width - 32))
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -188,13 +188,13 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve
|
|||||||
*/
|
*/
|
||||||
static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_background });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_background});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect);
|
||||||
|
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
set_font_colors(pixmap_gc, color_text, color_background);
|
set_font_colors(pixmap_gc, color_text, color_background);
|
||||||
draw_text(prompt, pixmap, pixmap_gc,
|
draw_text(prompt, pixmap, pixmap_gc,
|
||||||
4 + 4, 4 + 4, rect.width - 4 - 4);
|
4 + 4, 4 + 4, rect.width - 4 - 4);
|
||||||
|
|
||||||
/* render close button */
|
/* render close button */
|
||||||
const char *close_button_label = "X";
|
const char *close_button_label = "X";
|
||||||
@ -209,24 +209,23 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
values[1] = line_width;
|
values[1] = line_width;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
||||||
|
|
||||||
xcb_rectangle_t close = { y - w - (2 * line_width), 0, w + (2 * line_width), rect.height };
|
xcb_rectangle_t close = {y - w - (2 * line_width), 0, w + (2 * line_width), rect.height};
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
||||||
|
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_border });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
|
||||||
xcb_point_t points[] = {
|
xcb_point_t points[] = {
|
||||||
{ y - w - (2 * line_width), line_width / 2 },
|
{y - w - (2 * line_width), line_width / 2},
|
||||||
{ y - (line_width / 2), line_width / 2 },
|
{y - (line_width / 2), line_width / 2},
|
||||||
{ y - (line_width / 2), (rect.height - (line_width / 2)) - 2 },
|
{y - (line_width / 2), (rect.height - (line_width / 2)) - 2},
|
||||||
{ y - w - (2 * line_width), (rect.height - (line_width / 2)) - 2 },
|
{y - w - (2 * line_width), (rect.height - (line_width / 2)) - 2},
|
||||||
{ y - w - (2 * line_width), line_width / 2 }
|
{y - w - (2 * line_width), line_width / 2}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points);
|
||||||
|
|
||||||
values[0] = 1;
|
values[0] = 1;
|
||||||
set_font_colors(pixmap_gc, color_text, color_button_background);
|
set_font_colors(pixmap_gc, color_text, color_button_background);
|
||||||
/* the x term here seems to set left/right padding */
|
/* the x term here seems to set left/right padding */
|
||||||
draw_text_ascii(close_button_label, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4,
|
draw_text_ascii(close_button_label, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4,
|
||||||
4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4);
|
4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4);
|
||||||
y -= w;
|
y -= w;
|
||||||
|
|
||||||
y -= 20;
|
y -= 20;
|
||||||
@ -239,20 +238,19 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
/* account for left/right padding, which seems to be set to 12px (total) below */
|
/* account for left/right padding, which seems to be set to 12px (total) below */
|
||||||
w += 12;
|
w += 12;
|
||||||
y -= 30;
|
y -= 30;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_button_background });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_button_background});
|
||||||
close = (xcb_rectangle_t){ y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6 };
|
close = (xcb_rectangle_t) {y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6};
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
||||||
|
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_border });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
|
||||||
buttons[c].x = y - w - (2 * line_width);
|
buttons[c].x = y - w - (2 * line_width);
|
||||||
buttons[c].width = w;
|
buttons[c].width = w;
|
||||||
xcb_point_t points2[] = {
|
xcb_point_t points2[] = {
|
||||||
{ y - w - (2 * line_width), (line_width / 2) + 2 },
|
{y - w - (2 * line_width), (line_width / 2) + 2},
|
||||||
{ y - (line_width / 2), (line_width / 2) + 2 },
|
{y - (line_width / 2), (line_width / 2) + 2},
|
||||||
{ y - (line_width / 2), (rect.height - 4 - (line_width / 2)) },
|
{y - (line_width / 2), (rect.height - 4 - (line_width / 2))},
|
||||||
{ y - w - (2 * line_width), (rect.height - 4 - (line_width / 2)) },
|
{y - w - (2 * line_width), (rect.height - 4 - (line_width / 2))},
|
||||||
{ y - w - (2 * line_width), (line_width / 2) + 2 }
|
{y - w - (2 * line_width), (line_width / 2) + 2}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2);
|
||||||
|
|
||||||
values[0] = color_text;
|
values[0] = color_text;
|
||||||
@ -260,7 +258,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
set_font_colors(pixmap_gc, color_text, color_button_background);
|
set_font_colors(pixmap_gc, color_text, color_button_background);
|
||||||
/* the x term seems to set left/right padding */
|
/* the x term seems to set left/right padding */
|
||||||
draw_text(buttons[c].label, pixmap, pixmap_gc,
|
draw_text(buttons[c].label, pixmap, pixmap_gc,
|
||||||
y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6);
|
y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6);
|
||||||
|
|
||||||
y -= w;
|
y -= w;
|
||||||
}
|
}
|
||||||
@ -271,12 +269,10 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
values[1] = line_width;
|
values[1] = line_width;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
||||||
xcb_point_t bottom[] = {
|
xcb_point_t bottom[] = {
|
||||||
{ 0, rect.height - 0 },
|
{0, rect.height - 0},
|
||||||
{ rect.width, rect.height - 0 }
|
{rect.width, rect.height - 0}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 2, bottom);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 2, bottom);
|
||||||
|
|
||||||
|
|
||||||
/* Copy the contents of the pixmap to the real window */
|
/* Copy the contents of the pixmap to the real window */
|
||||||
xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, rect.width, rect.height);
|
xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, rect.width, rect.height);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
@ -322,7 +318,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1");
|
char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1");
|
||||||
int o, option_index = 0;
|
int o, option_index = 0;
|
||||||
enum { TYPE_ERROR = 0, TYPE_WARNING = 1 } bar_type = TYPE_ERROR;
|
enum { TYPE_ERROR = 0,
|
||||||
|
TYPE_WARNING = 1 } bar_type = TYPE_ERROR;
|
||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
@ -331,8 +328,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"message", required_argument, 0, 'm'},
|
{"message", required_argument, 0, 'm'},
|
||||||
{"type", required_argument, 0, 't'},
|
{"type", required_argument, 0, 't'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "b:f:m:t:vh";
|
char *options_string = "b:f:m:t:vh";
|
||||||
|
|
||||||
@ -363,8 +359,8 @@ int main(int argc, char *argv[]) {
|
|||||||
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
||||||
buttons[buttoncnt].action = argv[optind];
|
buttons[buttoncnt].action = argv[optind];
|
||||||
printf("button with label *%s* and action *%s*\n",
|
printf("button with label *%s* and action *%s*\n",
|
||||||
i3string_as_utf8(buttons[buttoncnt].label),
|
i3string_as_utf8(buttons[buttoncnt].label),
|
||||||
buttons[buttoncnt].action);
|
buttons[buttoncnt].action);
|
||||||
buttoncnt++;
|
buttoncnt++;
|
||||||
printf("now %d buttons\n", buttoncnt);
|
printf("now %d buttons\n", buttoncnt);
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
@ -378,11 +374,11 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_connection_has_error(conn))
|
xcb_connection_has_error(conn))
|
||||||
die("Cannot open display\n");
|
die("Cannot open display\n");
|
||||||
|
|
||||||
/* Place requests for the atoms we need as soon as possible */
|
/* Place requests for the atoms we need as soon as possible */
|
||||||
#define xmacro(atom) \
|
#define xmacro(atom) \
|
||||||
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(conn, screens);
|
root_screen = xcb_aux_get_screen(conn, screens);
|
||||||
root = root_screen->root;
|
root = root_screen->root;
|
||||||
@ -412,46 +408,45 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
50, 50, 500, font.height + 8 + 8 /* 8 px padding */, /* dimensions */
|
50, 50, 500, font.height + 8 + 8 /* 8 px padding */, /* dimensions */
|
||||||
0, /* x11 border = 0, we draw our own */
|
0, /* x11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS |
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
||||||
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_BUTTON_RELEASE});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define xmacro(name) \
|
#define xmacro(name) \
|
||||||
do { \
|
do { \
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
|
||||||
if (!reply) \
|
if (!reply) \
|
||||||
die("Could not get atom " # name "\n"); \
|
die("Could not get atom " #name "\n"); \
|
||||||
\
|
\
|
||||||
A_ ## name = reply->atom; \
|
A_##name = reply->atom; \
|
||||||
free(reply); \
|
free(reply); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
/* Set dock mode */
|
/* Set dock mode */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_WINDOW_TYPE,
|
A__NET_WM_WINDOW_TYPE,
|
||||||
A_ATOM,
|
A_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &A__NET_WM_WINDOW_TYPE_DOCK);
|
(unsigned char *)&A__NET_WM_WINDOW_TYPE_DOCK);
|
||||||
|
|
||||||
/* Reserve some space at the top of the screen */
|
/* Reserve some space at the top of the screen */
|
||||||
struct {
|
struct {
|
||||||
@ -475,13 +470,13 @@ int main(int argc, char *argv[]) {
|
|||||||
strut_partial.top_end_x = 800;
|
strut_partial.top_end_x = 800;
|
||||||
|
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_STRUT_PARTIAL,
|
A__NET_WM_STRUT_PARTIAL,
|
||||||
A_CARDINAL,
|
A_CARDINAL,
|
||||||
32,
|
32,
|
||||||
12,
|
12,
|
||||||
&strut_partial);
|
&strut_partial);
|
||||||
|
|
||||||
/* Create pixmap */
|
/* Create pixmap */
|
||||||
pixmap = xcb_generate_id(conn);
|
pixmap = xcb_generate_id(conn);
|
||||||
@ -504,25 +499,24 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
handle_expose(conn, (xcb_expose_event_t*)event);
|
handle_expose(conn, (xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
handle_button_press(conn, (xcb_button_press_event_t*)event);
|
handle_button_press(conn, (xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_BUTTON_RELEASE:
|
case XCB_BUTTON_RELEASE:
|
||||||
handle_button_release(conn, (xcb_button_release_event_t*)event);
|
handle_button_release(conn, (xcb_button_release_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_CONFIGURE_NOTIFY: {
|
case XCB_CONFIGURE_NOTIFY: {
|
||||||
xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t*)event;
|
xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t *)event;
|
||||||
rect = (xcb_rectangle_t){
|
rect = (xcb_rectangle_t) {
|
||||||
configure_notify->x,
|
configure_notify->x,
|
||||||
configure_notify->y,
|
configure_notify->y,
|
||||||
configure_notify->width,
|
configure_notify->width,
|
||||||
configure_notify->height
|
configure_notify->height};
|
||||||
};
|
|
||||||
|
|
||||||
/* Recreate the pixmap / gc */
|
/* Recreate the pixmap / gc */
|
||||||
xcb_free_pixmap(conn, pixmap);
|
xcb_free_pixmap(conn, pixmap);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
i3bar_child child;
|
i3bar_child child;
|
||||||
|
|
||||||
/* stdin- and sigchild-watchers */
|
/* stdin- and sigchild-watchers */
|
||||||
ev_io *stdin_io;
|
ev_io *stdin_io;
|
||||||
ev_child *child_sig;
|
ev_child *child_sig;
|
||||||
|
|
||||||
/* JSON parser for stdin */
|
/* JSON parser for stdin */
|
||||||
@ -80,7 +80,7 @@ static void clear_status_blocks() {
|
|||||||
* `draw_bars' is called, the error message text will be drawn on the bar in
|
* `draw_bars' is called, the error message text will be drawn on the bar in
|
||||||
* the space allocated for the statusline.
|
* the space allocated for the statusline.
|
||||||
*/
|
*/
|
||||||
__attribute__ ((format (printf, 1, 2))) static void set_statusline_error(const char *format, ...) {
|
__attribute__((format(printf, 1, 2))) static void set_statusline_error(const char *format, ...) {
|
||||||
clear_status_blocks();
|
clear_status_blocks();
|
||||||
|
|
||||||
char *message;
|
char *message;
|
||||||
@ -188,9 +188,9 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) {
|
|||||||
sasprintf(&(ctx->block.color), "%.*s", len, val);
|
sasprintf(&(ctx->block.color), "%.*s", len, val);
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "align") == 0) {
|
if (strcasecmp(ctx->last_map_key, "align") == 0) {
|
||||||
if (len == strlen("left") && !strncmp((const char*)val, "left", strlen("left"))) {
|
if (len == strlen("left") && !strncmp((const char *)val, "left", strlen("left"))) {
|
||||||
ctx->block.align = ALIGN_LEFT;
|
ctx->block.align = ALIGN_LEFT;
|
||||||
} else if (len == strlen("right") && !strncmp((const char*)val, "right", strlen("right"))) {
|
} else if (len == strlen("right") && !strncmp((const char *)val, "right", strlen("right"))) {
|
||||||
ctx->block.align = ALIGN_RIGHT;
|
ctx->block.align = ALIGN_RIGHT;
|
||||||
} else {
|
} else {
|
||||||
ctx->block.align = ALIGN_CENTER;
|
ctx->block.align = ALIGN_CENTER;
|
||||||
@ -201,13 +201,13 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) {
|
|||||||
i3string_free(text);
|
i3string_free(text);
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "name") == 0) {
|
if (strcasecmp(ctx->last_map_key, "name") == 0) {
|
||||||
char *copy = (char*)malloc(len+1);
|
char *copy = (char *)malloc(len + 1);
|
||||||
strncpy(copy, (const char *)val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = 0;
|
copy[len] = 0;
|
||||||
ctx->block.name = copy;
|
ctx->block.name = copy;
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "instance") == 0) {
|
if (strcasecmp(ctx->last_map_key, "instance") == 0) {
|
||||||
char *copy = (char*)malloc(len+1);
|
char *copy = (char *)malloc(len + 1);
|
||||||
strncpy(copy, (const char *)val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = 0;
|
copy[len] = 0;
|
||||||
ctx->block.instance = copy;
|
ctx->block.instance = copy;
|
||||||
@ -243,7 +243,7 @@ static int stdin_end_map(void *context) {
|
|||||||
static int stdin_end_array(void *context) {
|
static int stdin_end_array(void *context) {
|
||||||
DLOG("dumping statusline:\n");
|
DLOG("dumping statusline:\n");
|
||||||
struct status_block *current;
|
struct status_block *current;
|
||||||
TAILQ_FOREACH(current, &statusline_head, blocks) {
|
TAILQ_FOREACH (current, &statusline_head, blocks) {
|
||||||
DLOG("full_text = %s\n", i3string_as_utf8(current->full_text));
|
DLOG("full_text = %s\n", i3string_as_utf8(current->full_text));
|
||||||
DLOG("color = %s\n", current->color);
|
DLOG("color = %s\n", current->color);
|
||||||
}
|
}
|
||||||
@ -262,9 +262,9 @@ static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
|
|||||||
int n = 0;
|
int n = 0;
|
||||||
int rec = 0;
|
int rec = 0;
|
||||||
int buffer_len = STDIN_CHUNK_SIZE;
|
int buffer_len = STDIN_CHUNK_SIZE;
|
||||||
unsigned char *buffer = smalloc(buffer_len+1);
|
unsigned char *buffer = smalloc(buffer_len + 1);
|
||||||
buffer[0] = '\0';
|
buffer[0] = '\0';
|
||||||
while(1) {
|
while (1) {
|
||||||
n = read(fd, buffer + rec, buffer_len - rec);
|
n = read(fd, buffer + rec, buffer_len - rec);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
@ -300,9 +300,10 @@ static void read_flat_input(char *buffer, int length) {
|
|||||||
I3STRING_FREE(first->full_text);
|
I3STRING_FREE(first->full_text);
|
||||||
/* Remove the trailing newline and terminate the string at the same
|
/* Remove the trailing newline and terminate the string at the same
|
||||||
* time. */
|
* time. */
|
||||||
if (buffer[length-1] == '\n' || buffer[length-1] == '\r')
|
if (buffer[length - 1] == '\n' || buffer[length - 1] == '\r')
|
||||||
buffer[length-1] = '\0';
|
buffer[length - 1] = '\0';
|
||||||
else buffer[length] = '\0';
|
else
|
||||||
|
buffer[length] = '\0';
|
||||||
first->full_text = i3string_from_utf8(buffer);
|
first->full_text = i3string_from_utf8(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ static bool read_json_input(unsigned char *input, int length) {
|
|||||||
status, message, length, input);
|
status, message, length, input);
|
||||||
|
|
||||||
set_statusline_error("Could not parse JSON (%s)", message);
|
set_statusline_error("Could not parse JSON (%s)", message);
|
||||||
yajl_free_error(parser, (unsigned char*)message);
|
yajl_free_error(parser, (unsigned char *)message);
|
||||||
draw_bars(false);
|
draw_bars(false);
|
||||||
} else if (parser_context.has_urgent) {
|
} else if (parser_context.has_urgent) {
|
||||||
has_urgent = true;
|
has_urgent = true;
|
||||||
@ -342,7 +343,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
if (child.version > 0) {
|
if (child.version > 0) {
|
||||||
has_urgent = read_json_input(buffer, rec);
|
has_urgent = read_json_input(buffer, rec);
|
||||||
} else {
|
} else {
|
||||||
read_flat_input((char*)buffer, rec);
|
read_flat_input((char *)buffer, rec);
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
draw_bars(has_urgent);
|
draw_bars(has_urgent);
|
||||||
@ -376,7 +377,7 @@ void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
* full_text pointer later. */
|
* full_text pointer later. */
|
||||||
struct status_block *new_block = scalloc(sizeof(struct status_block));
|
struct status_block *new_block = scalloc(sizeof(struct status_block));
|
||||||
TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks);
|
TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks);
|
||||||
read_flat_input((char*)buffer, rec);
|
read_flat_input((char *)buffer, rec);
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
ev_io_stop(main_loop, stdin_io);
|
ev_io_stop(main_loop, stdin_io);
|
||||||
@ -394,8 +395,8 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
|
|||||||
int exit_status = WEXITSTATUS(watcher->rstatus);
|
int exit_status = WEXITSTATUS(watcher->rstatus);
|
||||||
|
|
||||||
ELOG("Child (pid: %d) unexpectedly exited with status %d\n",
|
ELOG("Child (pid: %d) unexpectedly exited with status %d\n",
|
||||||
child.pid,
|
child.pid,
|
||||||
exit_status);
|
exit_status);
|
||||||
|
|
||||||
/* this error is most likely caused by a user giving a nonexecutable or
|
/* this error is most likely caused by a user giving a nonexecutable or
|
||||||
* nonexistent file, so we will handle those cases separately. */
|
* nonexistent file, so we will handle those cases separately. */
|
||||||
@ -450,7 +451,7 @@ void start_child(char *command) {
|
|||||||
|
|
||||||
gen = yajl_gen_alloc(NULL);
|
gen = yajl_gen_alloc(NULL);
|
||||||
|
|
||||||
int pipe_in[2]; /* pipe we read from */
|
int pipe_in[2]; /* pipe we read from */
|
||||||
int pipe_out[2]; /* pipe we write to */
|
int pipe_out[2]; /* pipe we write to */
|
||||||
|
|
||||||
if (pipe(pipe_in) == -1)
|
if (pipe(pipe_in) == -1)
|
||||||
@ -473,7 +474,7 @@ void start_child(char *command) {
|
|||||||
dup2(pipe_out[0], STDIN_FILENO);
|
dup2(pipe_out[0], STDIN_FILENO);
|
||||||
|
|
||||||
setpgid(child.pid, 0);
|
setpgid(child.pid, 0);
|
||||||
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char*) NULL);
|
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char *)NULL);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
/* Parent-process. Reroute streams */
|
/* Parent-process. Reroute streams */
|
||||||
|
@ -31,7 +31,7 @@ static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t
|
|||||||
FREE(cur_key);
|
FREE(cur_key);
|
||||||
|
|
||||||
cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(cur_key, (const char*) keyVal, keyLen);
|
strncpy(cur_key, (const char *)keyVal, keyLen);
|
||||||
cur_key[keyLen] = '\0';
|
cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -65,29 +65,29 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
|||||||
|
|
||||||
if (!strcmp(cur_key, "mode")) {
|
if (!strcmp(cur_key, "mode")) {
|
||||||
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
||||||
config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "dock", strlen("dock")) ? M_DOCK
|
config.hide_on_modifier = (len == 4 && !strncmp((const char *)val, "dock", strlen("dock")) ? M_DOCK
|
||||||
: (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? M_HIDE
|
: (len == 4 && !strncmp((const char *)val, "hide", strlen("hide")) ? M_HIDE
|
||||||
: M_INVISIBLE));
|
: M_INVISIBLE));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "hidden_state")) {
|
if (!strcmp(cur_key, "hidden_state")) {
|
||||||
DLOG("hidden_state = %.*s, len = %d\n", len, val, len);
|
DLOG("hidden_state = %.*s, len = %d\n", len, val, len);
|
||||||
config.hidden_state = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? S_HIDE : S_SHOW);
|
config.hidden_state = (len == 4 && !strncmp((const char *)val, "hide", strlen("hide")) ? S_HIDE : S_SHOW);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "modifier")) {
|
if (!strcmp(cur_key, "modifier")) {
|
||||||
DLOG("modifier = %.*s\n", len, val);
|
DLOG("modifier = %.*s\n", len, val);
|
||||||
if (len == 5 && !strncmp((const char*)val, "shift", strlen("shift"))) {
|
if (len == 5 && !strncmp((const char *)val, "shift", strlen("shift"))) {
|
||||||
config.modifier = ShiftMask;
|
config.modifier = ShiftMask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (len == 4 && !strncmp((const char*)val, "ctrl", strlen("ctrl"))) {
|
if (len == 4 && !strncmp((const char *)val, "ctrl", strlen("ctrl"))) {
|
||||||
config.modifier = ControlMask;
|
config.modifier = ControlMask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (len == 4 && !strncmp((const char*)val, "Mod", strlen("Mod"))) {
|
if (len == 4 && !strncmp((const char *)val, "Mod", strlen("Mod"))) {
|
||||||
switch (val[3]) {
|
switch (val[3]) {
|
||||||
case '1':
|
case '1':
|
||||||
config.modifier = Mod1Mask;
|
config.modifier = Mod1Mask;
|
||||||
@ -114,7 +114,7 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
|||||||
|
|
||||||
if (!strcmp(cur_key, "position")) {
|
if (!strcmp(cur_key, "position")) {
|
||||||
DLOG("position = %.*s\n", len, val);
|
DLOG("position = %.*s\n", len, val);
|
||||||
config.position = (len == 3 && !strncmp((const char*)val, "top", strlen("top")) ? POS_TOP : POS_BOT);
|
config.position = (len == 3 && !strncmp((const char *)val, "top", strlen("top")) ? POS_TOP : POS_BOT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
|||||||
if (!strcmp(cur_key, "outputs")) {
|
if (!strcmp(cur_key, "outputs")) {
|
||||||
DLOG("+output %.*s\n", len, val);
|
DLOG("+output %.*s\n", len, val);
|
||||||
int new_num_outputs = config.num_outputs + 1;
|
int new_num_outputs = config.num_outputs + 1;
|
||||||
config.outputs = srealloc(config.outputs, sizeof(char*) * new_num_outputs);
|
config.outputs = srealloc(config.outputs, sizeof(char *) * new_num_outputs);
|
||||||
sasprintf(&config.outputs[config.num_outputs], "%.*s", len, val);
|
sasprintf(&config.outputs[config.num_outputs], "%.*s", len, val);
|
||||||
config.num_outputs = new_num_outputs;
|
config.num_outputs = new_num_outputs;
|
||||||
return 1;
|
return 1;
|
||||||
@ -146,13 +146,13 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COLOR(json_name, struct_name) \
|
#define COLOR(json_name, struct_name) \
|
||||||
do { \
|
do { \
|
||||||
if (!strcmp(cur_key, #json_name)) { \
|
if (!strcmp(cur_key, #json_name)) { \
|
||||||
DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \
|
DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \
|
||||||
sasprintf(&(config.colors.struct_name), "%.*s", len, val); \
|
sasprintf(&(config.colors.struct_name), "%.*s", len, val); \
|
||||||
return 1; \
|
return 1; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
COLOR(statusline, bar_fg);
|
COLOR(statusline, bar_fg);
|
||||||
@ -225,7 +225,7 @@ void parse_config_json(char *json) {
|
|||||||
yajl_status state;
|
yajl_status state;
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
/* FIXME: Proper errorhandling for JSON-parsing */
|
/* FIXME: Proper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -246,9 +246,9 @@ void parse_config_json(char *json) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void free_colors(struct xcb_color_strings_t *colors) {
|
void free_colors(struct xcb_color_strings_t *colors) {
|
||||||
#define FREE_COLOR(x) \
|
#define FREE_COLOR(x) \
|
||||||
do { \
|
do { \
|
||||||
if (colors->x) \
|
if (colors->x) \
|
||||||
free(colors->x); \
|
free(colors->x); \
|
||||||
} while (0)
|
} while (0)
|
||||||
FREE_COLOR(bar_fg);
|
FREE_COLOR(bar_fg);
|
||||||
@ -268,4 +268,3 @@ void free_colors(struct xcb_color_strings_t *colors) {
|
|||||||
FREE_COLOR(focus_ws_border);
|
FREE_COLOR(focus_ws_border);
|
||||||
#undef FREE_COLOR
|
#undef FREE_COLOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
ev_io *i3_connection;
|
ev_io *i3_connection;
|
||||||
|
|
||||||
const char *sock_path;
|
const char *sock_path;
|
||||||
|
|
||||||
typedef void(*handler_t)(char*);
|
typedef void (*handler_t)(char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called, when we get a reply to a command from i3.
|
* Called, when we get a reply to a command from i3.
|
||||||
@ -67,7 +67,7 @@ void got_output_reply(char *reply) {
|
|||||||
reconfig_windows(false);
|
reconfig_windows(false);
|
||||||
|
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
kick_tray_clients(o_walk);
|
kick_tray_clients(o_walk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ void got_bar_config_update(char *event) {
|
|||||||
char *found_id = strstr(event, expected_id);
|
char *found_id = strstr(event, expected_id);
|
||||||
FREE(expected_id);
|
FREE(expected_id);
|
||||||
if (found_id == NULL)
|
if (found_id == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free_colors(&(config.colors));
|
free_colors(&(config.colors));
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
int fd = watcher->fd;
|
int fd = watcher->fd;
|
||||||
|
|
||||||
/* First we only read the header, because we know its length */
|
/* First we only read the header, because we know its length */
|
||||||
uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t)*2;
|
uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) * 2;
|
||||||
char *header = smalloc(header_len);
|
char *header = smalloc(header_len);
|
||||||
|
|
||||||
/* We first parse the fixed-length IPC-header, to know, how much data
|
/* We first parse the fixed-length IPC-header, to know, how much data
|
||||||
@ -217,7 +217,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
|
|
||||||
if (strncmp(header, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC))) {
|
if (strncmp(header, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC))) {
|
||||||
ELOG("Wrong magic code: %.*s\n Expected: %s\n",
|
ELOG("Wrong magic code: %.*s\n Expected: %s\n",
|
||||||
(int) strlen(I3_IPC_MAGIC),
|
(int)strlen(I3_IPC_MAGIC),
|
||||||
header,
|
header,
|
||||||
I3_IPC_MAGIC);
|
I3_IPC_MAGIC);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -225,10 +225,10 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
|
|
||||||
char *walk = header + strlen(I3_IPC_MAGIC);
|
char *walk = header + strlen(I3_IPC_MAGIC);
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
memcpy(&size, (uint32_t*)walk, sizeof(uint32_t));
|
memcpy(&size, (uint32_t *)walk, sizeof(uint32_t));
|
||||||
walk += sizeof(uint32_t);
|
walk += sizeof(uint32_t);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
memcpy(&type, (uint32_t*)walk, sizeof(uint32_t));
|
memcpy(&type, (uint32_t *)walk, sizeof(uint32_t));
|
||||||
|
|
||||||
/* Now that we know, what to expect, we can start read()ing the rest
|
/* Now that we know, what to expect, we can start read()ing the rest
|
||||||
* of the message */
|
* of the message */
|
||||||
@ -274,7 +274,7 @@ int i3_send_msg(uint32_t type, const char *payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We are a wellbehaved client and send a proper header first */
|
/* We are a wellbehaved client and send a proper header first */
|
||||||
uint32_t to_write = strlen (I3_IPC_MAGIC) + sizeof(uint32_t)*2 + len;
|
uint32_t to_write = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) * 2 + len;
|
||||||
/* TODO: I'm not entirely sure if this buffer really has to contain more
|
/* TODO: I'm not entirely sure if this buffer really has to contain more
|
||||||
* than the pure header (why not just write() the payload from *payload?),
|
* than the pure header (why not just write() the payload from *payload?),
|
||||||
* but we leave it for now */
|
* but we leave it for now */
|
||||||
|
@ -99,12 +99,11 @@ int main(int argc, char **argv) {
|
|||||||
memset(&config, '\0', sizeof(config_t));
|
memset(&config, '\0', sizeof(config_t));
|
||||||
|
|
||||||
static struct option long_opt[] = {
|
static struct option long_opt[] = {
|
||||||
{ "socket", required_argument, 0, 's' },
|
{"socket", required_argument, 0, 's'},
|
||||||
{ "bar_id", required_argument, 0, 'b' },
|
{"bar_id", required_argument, 0, 'b'},
|
||||||
{ "help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h'},
|
||||||
{ "version", no_argument, 0, 'v' },
|
{"version", no_argument, 0, 'v'},
|
||||||
{ NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "b:s:hv", long_opt, &option_index)) != -1) {
|
while ((opt = getopt_long(argc, argv, "b:s:hv", long_opt, &option_index)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct mode_json_params {
|
struct mode_json_params {
|
||||||
char *json;
|
char *json;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
mode *mode;
|
mode *mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -28,22 +28,21 @@ struct mode_json_params {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
struct mode_json_params *params = (struct mode_json_params*) params_;
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "change")) {
|
if (!strcmp(params->cur_key, "change")) {
|
||||||
|
/* Save the name */
|
||||||
|
params->mode->name = i3string_from_utf8_with_length((const char *)val, len);
|
||||||
|
/* Save its rendered width */
|
||||||
|
params->mode->width = predict_text_width(params->mode->name);
|
||||||
|
|
||||||
/* Save the name */
|
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
||||||
params->mode->name = i3string_from_utf8_with_length((const char *)val, len);
|
FREE(params->cur_key);
|
||||||
/* Save its rendered width */
|
|
||||||
params->mode->width = predict_text_width(params->mode->name);
|
|
||||||
|
|
||||||
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
return 1;
|
||||||
FREE(params->cur_key);
|
}
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -53,11 +52,11 @@ static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
struct mode_json_params *params = (struct mode_json_params*) params_;
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -87,9 +86,9 @@ void parse_mode_json(char *json) {
|
|||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
|
|
||||||
handle = yajl_alloc(&mode_callbacks, NULL, (void*) ¶ms);
|
handle = yajl_alloc(&mode_callbacks, NULL, (void *)¶ms);
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct outputs_json_params {
|
struct outputs_json_params {
|
||||||
struct outputs_head *outputs;
|
struct outputs_head *outputs;
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
char *json;
|
char *json;
|
||||||
bool in_rect;
|
bool in_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -31,7 +31,7 @@ struct outputs_json_params {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_null_cb(void *params_) {
|
static int outputs_null_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ static int outputs_null_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_boolean_cb(void *params_, int val) {
|
static int outputs_boolean_cb(void *params_, int val) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "active")) {
|
if (!strcmp(params->cur_key, "active")) {
|
||||||
params->outputs_walk->active = val;
|
params->outputs_walk->active = val;
|
||||||
@ -65,34 +65,34 @@ static int outputs_boolean_cb(void *params_, int val) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_integer_cb(void *params_, long long val) {
|
static int outputs_integer_cb(void *params_, long long val) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "current_workspace")) {
|
if (!strcmp(params->cur_key, "current_workspace")) {
|
||||||
params->outputs_walk->ws = (int) val;
|
params->outputs_walk->ws = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "x")) {
|
if (!strcmp(params->cur_key, "x")) {
|
||||||
params->outputs_walk->rect.x = (int) val;
|
params->outputs_walk->rect.x = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "y")) {
|
if (!strcmp(params->cur_key, "y")) {
|
||||||
params->outputs_walk->rect.y = (int) val;
|
params->outputs_walk->rect.y = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "width")) {
|
if (!strcmp(params->cur_key, "width")) {
|
||||||
params->outputs_walk->rect.w = (int) val;
|
params->outputs_walk->rect.w = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "height")) {
|
if (!strcmp(params->cur_key, "height")) {
|
||||||
params->outputs_walk->rect.h = (int) val;
|
params->outputs_walk->rect.h = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -105,11 +105,11 @@ static int outputs_integer_cb(void *params_, long long val) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int outputs_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "current_workspace")) {
|
if (!strcmp(params->cur_key, "current_workspace")) {
|
||||||
char *copy = smalloc(sizeof(const unsigned char) * (len + 1));
|
char *copy = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(copy, (const char*) val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = '\0';
|
copy[len] = '\0';
|
||||||
|
|
||||||
char *end;
|
char *end;
|
||||||
@ -128,7 +128,7 @@ static int outputs_string_cb(void *params_, const unsigned char *val, size_t len
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *name = smalloc(sizeof(const unsigned char) * (len + 1));
|
char *name = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(name, (const char*) val, len);
|
strncpy(name, (const char *)val, len);
|
||||||
name[len] = '\0';
|
name[len] = '\0';
|
||||||
|
|
||||||
params->outputs_walk->name = name;
|
params->outputs_walk->name = name;
|
||||||
@ -143,7 +143,7 @@ static int outputs_string_cb(void *params_, const unsigned char *val, size_t len
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_start_map_cb(void *params_) {
|
static int outputs_start_map_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
i3_output *new_output = NULL;
|
i3_output *new_output = NULL;
|
||||||
|
|
||||||
if (params->cur_key == NULL) {
|
if (params->cur_key == NULL) {
|
||||||
@ -176,7 +176,7 @@ static int outputs_start_map_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_end_map_cb(void *params_) {
|
static int outputs_end_map_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
if (params->in_rect) {
|
if (params->in_rect) {
|
||||||
params->in_rect = false;
|
params->in_rect = false;
|
||||||
/* Ignore the end of a rect */
|
/* Ignore the end of a rect */
|
||||||
@ -225,11 +225,11 @@ static int outputs_end_map_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -269,9 +269,9 @@ void parse_outputs_json(char *json) {
|
|||||||
|
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, (void*) ¶ms);
|
handle = yajl_alloc(&outputs_callbacks, NULL, (void *)¶ms);
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -296,7 +296,7 @@ i3_output *get_output_by_name(char *name) {
|
|||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!strcmp(walk->name, name)) {
|
if (!strcmp(walk->name, name)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ static int header_boolean(void *ctx, int val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_KEY(name) (stringlen == strlen(name) && \
|
#define CHECK_KEY(name) (stringlen == strlen(name) && \
|
||||||
STARTS_WITH((const char*)stringval, stringlen, name))
|
STARTS_WITH((const char *)stringval, stringlen, name))
|
||||||
|
|
||||||
static int header_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
static int header_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
||||||
if (CHECK_KEY("version")) {
|
if (CHECK_KEY("version")) {
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct workspaces_json_params {
|
struct workspaces_json_params {
|
||||||
struct ws_head *workspaces;
|
struct ws_head *workspaces;
|
||||||
i3_ws *workspaces_walk;
|
i3_ws *workspaces_walk;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
char *json;
|
char *json;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -29,7 +29,7 @@ struct workspaces_json_params {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_boolean_cb(void *params_, int val) {
|
static int workspaces_boolean_cb(void *params_, int val) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "visible")) {
|
if (!strcmp(params->cur_key, "visible")) {
|
||||||
params->workspaces_walk->visible = val;
|
params->workspaces_walk->visible = val;
|
||||||
@ -59,34 +59,34 @@ static int workspaces_boolean_cb(void *params_, int val) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_integer_cb(void *params_, long long val) {
|
static int workspaces_integer_cb(void *params_, long long val) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "num")) {
|
if (!strcmp(params->cur_key, "num")) {
|
||||||
params->workspaces_walk->num = (int) val;
|
params->workspaces_walk->num = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "x")) {
|
if (!strcmp(params->cur_key, "x")) {
|
||||||
params->workspaces_walk->rect.x = (int) val;
|
params->workspaces_walk->rect.x = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "y")) {
|
if (!strcmp(params->cur_key, "y")) {
|
||||||
params->workspaces_walk->rect.y = (int) val;
|
params->workspaces_walk->rect.y = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "width")) {
|
if (!strcmp(params->cur_key, "width")) {
|
||||||
params->workspaces_walk->rect.w = (int) val;
|
params->workspaces_walk->rect.w = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "height")) {
|
if (!strcmp(params->cur_key, "height")) {
|
||||||
params->workspaces_walk->rect.h = (int) val;
|
params->workspaces_walk->rect.h = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -100,70 +100,70 @@ static int workspaces_integer_cb(void *params_, long long val) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int workspaces_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
char *output_name;
|
char *output_name;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "name")) {
|
if (!strcmp(params->cur_key, "name")) {
|
||||||
const char *ws_name = (const char*)val;
|
const char *ws_name = (const char *)val;
|
||||||
params->workspaces_walk->canonical_name = strndup(ws_name, len);
|
params->workspaces_walk->canonical_name = strndup(ws_name, len);
|
||||||
|
|
||||||
if (config.strip_ws_numbers && params->workspaces_walk->num >= 0) {
|
if (config.strip_ws_numbers && params->workspaces_walk->num >= 0) {
|
||||||
/* Special case: strip off the workspace number */
|
/* Special case: strip off the workspace number */
|
||||||
static char ws_num[10];
|
static char ws_num[10];
|
||||||
|
|
||||||
snprintf(ws_num, sizeof(ws_num), "%d", params->workspaces_walk->num);
|
snprintf(ws_num, sizeof(ws_num), "%d", params->workspaces_walk->num);
|
||||||
|
|
||||||
/* Calculate the length of the number str in the name */
|
/* Calculate the length of the number str in the name */
|
||||||
size_t offset = strspn(ws_name, ws_num);
|
size_t offset = strspn(ws_name, ws_num);
|
||||||
|
|
||||||
/* Also strip off the conventional ws name delimiter */
|
/* Also strip off the conventional ws name delimiter */
|
||||||
if (offset && ws_name[offset] == ':')
|
if (offset && ws_name[offset] == ':')
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
/* Offset may be equal to length, in which case display the number */
|
/* Offset may be equal to length, in which case display the number */
|
||||||
params->workspaces_walk->name = (offset < len
|
params->workspaces_walk->name = (offset < len
|
||||||
? i3string_from_utf8_with_length(ws_name + offset, len - offset)
|
? i3string_from_utf8_with_length(ws_name + offset, len - offset)
|
||||||
: i3string_from_utf8(ws_num));
|
: i3string_from_utf8(ws_num));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Default case: just save the name */
|
/* Default case: just save the name */
|
||||||
params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len);
|
params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len);
|
||||||
}
|
|
||||||
|
|
||||||
/* Save its rendered width */
|
|
||||||
params->workspaces_walk->name_width =
|
|
||||||
predict_text_width(params->workspaces_walk->name);
|
|
||||||
|
|
||||||
DLOG("Got Workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n",
|
|
||||||
params->workspaces_walk->canonical_name,
|
|
||||||
i3string_as_utf8(params->workspaces_walk->name),
|
|
||||||
params->workspaces_walk->name_width,
|
|
||||||
i3string_get_num_glyphs(params->workspaces_walk->name));
|
|
||||||
FREE(params->cur_key);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "output")) {
|
/* Save its rendered width */
|
||||||
/* We add the ws to the TAILQ of the output, it belongs to */
|
params->workspaces_walk->name_width =
|
||||||
output_name = smalloc(sizeof(const unsigned char) * (len + 1));
|
predict_text_width(params->workspaces_walk->name);
|
||||||
strncpy(output_name, (const char*) val, len);
|
|
||||||
output_name[len] = '\0';
|
|
||||||
i3_output *target = get_output_by_name(output_name);
|
|
||||||
if (target) {
|
|
||||||
params->workspaces_walk->output = target;
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
DLOG("Got Workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n",
|
||||||
params->workspaces_walk,
|
params->workspaces_walk->canonical_name,
|
||||||
tailq);
|
i3string_as_utf8(params->workspaces_walk->name),
|
||||||
}
|
params->workspaces_walk->name_width,
|
||||||
|
i3string_get_num_glyphs(params->workspaces_walk->name));
|
||||||
|
FREE(params->cur_key);
|
||||||
|
|
||||||
FREE(output_name);
|
return 1;
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
if (!strcmp(params->cur_key, "output")) {
|
||||||
|
/* We add the ws to the TAILQ of the output, it belongs to */
|
||||||
|
output_name = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
|
strncpy(output_name, (const char *)val, len);
|
||||||
|
output_name[len] = '\0';
|
||||||
|
i3_output *target = get_output_by_name(output_name);
|
||||||
|
if (target) {
|
||||||
|
params->workspaces_walk->output = target;
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
||||||
|
params->workspaces_walk,
|
||||||
|
tailq);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
FREE(output_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -171,7 +171,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_start_map_cb(void *params_) {
|
static int workspaces_start_map_cb(void *params_) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
i3_ws *new_workspace = NULL;
|
i3_ws *new_workspace = NULL;
|
||||||
|
|
||||||
@ -199,11 +199,11 @@ static int workspaces_start_map_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -235,9 +235,9 @@ void parse_workspaces_json(char *json) {
|
|||||||
|
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
handle = yajl_alloc(&workspaces_callbacks, NULL, (void*) ¶ms);
|
handle = yajl_alloc(&workspaces_callbacks, NULL, (void *)¶ms);
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -264,11 +264,11 @@ void free_workspaces(void) {
|
|||||||
if (outputs == NULL) {
|
if (outputs == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i3_ws *ws_walk;
|
i3_ws *ws_walk;
|
||||||
|
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
|
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
I3STRING_FREE(ws_walk->name);
|
I3STRING_FREE(ws_walk->name);
|
||||||
FREE(ws_walk->canonical_name);
|
FREE(ws_walk->canonical_name);
|
||||||
}
|
}
|
||||||
|
307
i3bar/src/xcb.c
307
i3bar/src/xcb.c
@ -35,19 +35,19 @@
|
|||||||
|
|
||||||
/* We save the Atoms in an easy to access array, indexed by an enum */
|
/* We save the Atoms in an easy to access array, indexed by an enum */
|
||||||
enum {
|
enum {
|
||||||
#define ATOM_DO(name) name,
|
#define ATOM_DO(name) name,
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
NUM_ATOMS
|
NUM_ATOMS
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
|
xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
|
||||||
xcb_atom_t atoms[NUM_ATOMS];
|
xcb_atom_t atoms[NUM_ATOMS];
|
||||||
|
|
||||||
/* Variables, that are the same for all functions at all times */
|
/* Variables, that are the same for all functions at all times */
|
||||||
xcb_connection_t *xcb_connection;
|
xcb_connection_t *xcb_connection;
|
||||||
int screen;
|
int screen;
|
||||||
xcb_screen_t *root_screen;
|
xcb_screen_t *root_screen;
|
||||||
xcb_window_t xcb_root;
|
xcb_window_t xcb_root;
|
||||||
|
|
||||||
/* selection window for tray support */
|
/* selection window for tray support */
|
||||||
static xcb_window_t selwin = XCB_NONE;
|
static xcb_window_t selwin = XCB_NONE;
|
||||||
@ -63,22 +63,22 @@ static i3Font font;
|
|||||||
int bar_height;
|
int bar_height;
|
||||||
|
|
||||||
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
||||||
Display *xkb_dpy;
|
Display *xkb_dpy;
|
||||||
int xkb_event_base;
|
int xkb_event_base;
|
||||||
int mod_pressed = 0;
|
int mod_pressed = 0;
|
||||||
|
|
||||||
/* Because the statusline is the same on all outputs, we have
|
/* Because the statusline is the same on all outputs, we have
|
||||||
* global buffer to render it on */
|
* global buffer to render it on */
|
||||||
xcb_gcontext_t statusline_ctx;
|
xcb_gcontext_t statusline_ctx;
|
||||||
xcb_gcontext_t statusline_clear;
|
xcb_gcontext_t statusline_clear;
|
||||||
xcb_pixmap_t statusline_pm;
|
xcb_pixmap_t statusline_pm;
|
||||||
uint32_t statusline_width;
|
uint32_t statusline_width;
|
||||||
|
|
||||||
/* Event-Watchers, to interact with the user */
|
/* Event-Watchers, to interact with the user */
|
||||||
ev_prepare *xcb_prep;
|
ev_prepare *xcb_prep;
|
||||||
ev_check *xcb_chk;
|
ev_check *xcb_chk;
|
||||||
ev_io *xcb_io;
|
ev_io *xcb_io;
|
||||||
ev_io *xkb_io;
|
ev_io *xkb_io;
|
||||||
|
|
||||||
/* The name of current binding mode */
|
/* The name of current binding mode */
|
||||||
static mode binding;
|
static mode binding;
|
||||||
@ -128,7 +128,7 @@ void refresh_statusline(void) {
|
|||||||
statusline_width = 0;
|
statusline_width = 0;
|
||||||
|
|
||||||
/* Predict the text width of all blocks (in pixels). */
|
/* Predict the text width of all blocks (in pixels). */
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
if (i3string_get_num_bytes(block->full_text) == 0)
|
if (i3string_get_num_bytes(block->full_text) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -168,12 +168,12 @@ void refresh_statusline(void) {
|
|||||||
realloc_sl_buffer();
|
realloc_sl_buffer();
|
||||||
|
|
||||||
/* Clear the statusline pixmap. */
|
/* Clear the statusline pixmap. */
|
||||||
xcb_rectangle_t rect = { 0, 0, root_screen->width_in_pixels, font.height + logical_px(5) };
|
xcb_rectangle_t rect = {0, 0, root_screen->width_in_pixels, font.height + logical_px(5)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect);
|
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect);
|
||||||
|
|
||||||
/* Draw the text of each block. */
|
/* Draw the text of each block. */
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
if (i3string_get_num_bytes(block->full_text) == 0)
|
if (i3string_get_num_bytes(block->full_text) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -184,14 +184,14 @@ void refresh_statusline(void) {
|
|||||||
|
|
||||||
if (TAILQ_NEXT(block, blocks) != NULL && !block->no_separator && block->sep_block_width > 0) {
|
if (TAILQ_NEXT(block, blocks) != NULL && !block->no_separator && block->sep_block_width > 0) {
|
||||||
/* This is not the last block, draw a separator. */
|
/* This is not the last block, draw a separator. */
|
||||||
uint32_t sep_offset = block->sep_block_width/2 + block->sep_block_width % 2;
|
uint32_t sep_offset = block->sep_block_width / 2 + block->sep_block_width % 2;
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH;
|
||||||
uint32_t values[] = { colors.sep_fg, colors.bar_bg, logical_px(1) };
|
uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)};
|
||||||
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
||||||
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
|
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
|
||||||
statusline_ctx, 2,
|
statusline_ctx, 2,
|
||||||
(xcb_point_t[]){ { x - sep_offset, 2 },
|
(xcb_point_t[]) {{x - sep_offset, 2},
|
||||||
{ x - sep_offset, font.height - 2 } });
|
{x - sep_offset, font.height - 2}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ void hide_bars(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active) {
|
if (!walk->active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -224,14 +224,14 @@ void unhide_bars(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
uint32_t values[5];
|
uint32_t values[5];
|
||||||
|
|
||||||
cont_child();
|
cont_child();
|
||||||
|
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (walk->bar == XCB_NONE) {
|
if (walk->bar == XCB_NONE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -243,7 +243,8 @@ void unhide_bars(void) {
|
|||||||
values[0] = walk->rect.x;
|
values[0] = walk->rect.x;
|
||||||
if (config.position == POS_TOP)
|
if (config.position == POS_TOP)
|
||||||
values[1] = walk->rect.y;
|
values[1] = walk->rect.y;
|
||||||
else values[1] = walk->rect.y + walk->rect.h - bar_height;
|
else
|
||||||
|
values[1] = walk->rect.y + walk->rect.h - bar_height;
|
||||||
values[2] = walk->rect.w;
|
values[2] = walk->rect.w;
|
||||||
values[3] = bar_height;
|
values[3] = bar_height;
|
||||||
values[4] = XCB_STACK_MODE_ABOVE;
|
values[4] = XCB_STACK_MODE_ABOVE;
|
||||||
@ -265,10 +266,10 @@ void unhide_bars(void) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void init_colors(const struct xcb_color_strings_t *new_colors) {
|
void init_colors(const struct xcb_color_strings_t *new_colors) {
|
||||||
#define PARSE_COLOR(name, def) \
|
#define PARSE_COLOR(name, def) \
|
||||||
do { \
|
do { \
|
||||||
colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \
|
colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \
|
||||||
} while (0)
|
} while (0)
|
||||||
PARSE_COLOR(bar_fg, "#FFFFFF");
|
PARSE_COLOR(bar_fg, "#FFFFFF");
|
||||||
PARSE_COLOR(bar_bg, "#000000");
|
PARSE_COLOR(bar_bg, "#000000");
|
||||||
PARSE_COLOR(sep_fg, "#666666");
|
PARSE_COLOR(sep_fg, "#666666");
|
||||||
@ -302,7 +303,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
/* Determine, which bar was clicked */
|
/* Determine, which bar was clicked */
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
xcb_window_t bar = event->event;
|
xcb_window_t bar = event->event;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (walk->bar == bar) {
|
if (walk->bar == bar) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -314,7 +315,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Move this to extern get_ws_for_output() */
|
/* TODO: Move this to extern get_ws_for_output() */
|
||||||
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
if (cur_ws->visible) {
|
if (cur_ws->visible) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -337,7 +338,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
/* First calculate width of tray area */
|
/* First calculate width of tray area */
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
int tray_width = 0;
|
int tray_width = 0;
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, walk->trayclients, tc_head, tailq) {
|
TAILQ_FOREACH_REVERSE (trayclient, walk->trayclients, tc_head, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
tray_width += (font.height + logical_px(2));
|
tray_width += (font.height + logical_px(2));
|
||||||
@ -350,7 +351,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
if (x >= 0) {
|
if (x >= 0) {
|
||||||
struct status_block *block;
|
struct status_block *block;
|
||||||
|
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
last_block_x = block_x;
|
last_block_x = block_x;
|
||||||
block_x += block->width + block->x_offset + block->x_append;
|
block_x += block->width + block->x_offset + block->x_append;
|
||||||
|
|
||||||
@ -386,7 +387,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Check if this event regards a workspace button */
|
/* Check if this event regards a workspace button */
|
||||||
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
DLOG("x = %d\n", x);
|
DLOG("x = %d\n", x);
|
||||||
if (x >= 0 && x < cur_ws->name_width + logical_px(10)) {
|
if (x >= 0 && x < cur_ws->name_width + logical_px(10)) {
|
||||||
break;
|
break;
|
||||||
@ -397,7 +398,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
/* Otherwise, focus our currently visible workspace if it is not
|
/* Otherwise, focus our currently visible workspace if it is not
|
||||||
* already focused */
|
* already focused */
|
||||||
if (cur_ws == NULL) {
|
if (cur_ws == NULL) {
|
||||||
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
if (cur_ws->visible && !cur_ws->focused)
|
if (cur_ws->visible && !cur_ws->focused)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -428,7 +429,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const size_t len = namelen + strlen("workspace \"\"") + 1;
|
const size_t len = namelen + strlen("workspace \"\"") + 1;
|
||||||
char *buffer = scalloc(len+num_quotes);
|
char *buffer = scalloc(len + num_quotes);
|
||||||
strncpy(buffer, "workspace \"", strlen("workspace \""));
|
strncpy(buffer, "workspace \"", strlen("workspace \""));
|
||||||
size_t inpos, outpos;
|
size_t inpos, outpos;
|
||||||
for (inpos = 0, outpos = strlen("workspace \"");
|
for (inpos = 0, outpos = strlen("workspace \"");
|
||||||
@ -454,12 +455,12 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
static void configure_trayclients(void) {
|
static void configure_trayclients(void) {
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int clients = 0;
|
int clients = 0;
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
|
TAILQ_FOREACH_REVERSE (trayclient, output->trayclients, tc_head, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
clients++;
|
clients++;
|
||||||
@ -482,7 +483,7 @@ static void configure_trayclients(void) {
|
|||||||
* supported client messages currently are _NET_SYSTEM_TRAY_OPCODE.
|
* supported client messages currently are _NET_SYSTEM_TRAY_OPCODE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_client_message(xcb_client_message_event_t* event) {
|
static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
|
if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
|
||||||
event->format == 32) {
|
event->format == 32) {
|
||||||
DLOG("_NET_SYSTEM_TRAY_OPCODE received\n");
|
DLOG("_NET_SYSTEM_TRAY_OPCODE received\n");
|
||||||
@ -543,7 +544,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
|
|
||||||
DLOG("X window %08x requested docking\n", client);
|
DLOG("X window %08x requested docking\n", client);
|
||||||
i3_output *walk, *output = NULL;
|
i3_output *walk, *output = NULL;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
if (config.tray_output) {
|
if (config.tray_output) {
|
||||||
@ -561,7 +562,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
if (output == NULL &&
|
if (output == NULL &&
|
||||||
config.tray_output &&
|
config.tray_output &&
|
||||||
strcasecmp("primary", config.tray_output) == 0) {
|
strcasecmp("primary", config.tray_output) == 0) {
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("Falling back to output %s because no primary output is configured\n", walk->name);
|
DLOG("Falling back to output %s because no primary output is configured\n", walk->name);
|
||||||
@ -606,7 +607,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
0,
|
0,
|
||||||
client,
|
client,
|
||||||
XCB_EVENT_MASK_NO_EVENT,
|
XCB_EVENT_MASK_NO_EVENT,
|
||||||
(char*)ev);
|
(char *)ev);
|
||||||
free(event);
|
free(event);
|
||||||
|
|
||||||
/* Put the client inside the save set. Upon termination (whether
|
/* Put the client inside the save set. Upon termination (whether
|
||||||
@ -645,16 +646,16 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
* See: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
* See: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_destroy_notify(xcb_destroy_notify_event_t* event) {
|
static void handle_destroy_notify(xcb_destroy_notify_event_t *event) {
|
||||||
DLOG("DestroyNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("DestroyNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -674,16 +675,16 @@ static void handle_destroy_notify(xcb_destroy_notify_event_t* event) {
|
|||||||
* window. We respond by realigning the tray clients.
|
* window. We respond by realigning the tray clients.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_map_notify(xcb_map_notify_event_t* event) {
|
static void handle_map_notify(xcb_map_notify_event_t *event) {
|
||||||
DLOG("MapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("MapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -702,16 +703,16 @@ static void handle_map_notify(xcb_map_notify_event_t* event) {
|
|||||||
* window. We respond by realigning the tray clients.
|
* window. We respond by realigning the tray clients.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_unmap_notify(xcb_unmap_notify_event_t* event) {
|
static void handle_unmap_notify(xcb_unmap_notify_event_t *event) {
|
||||||
DLOG("UnmapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("UnmapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -738,11 +739,11 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
|
|||||||
DLOG("xembed_info updated\n");
|
DLOG("xembed_info updated\n");
|
||||||
trayclient *trayclient = NULL, *walk;
|
trayclient *trayclient = NULL, *walk;
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
if (!o_walk->active)
|
if (!o_walk->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TAILQ_FOREACH(walk, o_walk->trayclients, tailq) {
|
TAILQ_FOREACH (walk, o_walk->trayclients, tailq) {
|
||||||
if (walk->win != event->window)
|
if (walk->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
trayclient = walk;
|
trayclient = walk;
|
||||||
@ -801,12 +802,12 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
|
|||||||
|
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int clients = 0;
|
int clients = 0;
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
|
TAILQ_FOREACH_REVERSE (trayclient, output->trayclients, tc_head, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
clients++;
|
clients++;
|
||||||
@ -860,31 +861,31 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
|
|||||||
break;
|
break;
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
/* Button-press-events are mouse-buttons clicked on one of our bars */
|
/* Button-press-events are mouse-buttons clicked on one of our bars */
|
||||||
handle_button((xcb_button_press_event_t*) event);
|
handle_button((xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
/* Client messages are used for client-to-client communication, for
|
/* Client messages are used for client-to-client communication, for
|
||||||
* example system tray widgets talk to us directly via client messages. */
|
* example system tray widgets talk to us directly via client messages. */
|
||||||
handle_client_message((xcb_client_message_event_t*) event);
|
handle_client_message((xcb_client_message_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY:
|
||||||
/* DestroyNotify signifies the end of the XEmbed protocol */
|
/* DestroyNotify signifies the end of the XEmbed protocol */
|
||||||
handle_destroy_notify((xcb_destroy_notify_event_t*) event);
|
handle_destroy_notify((xcb_destroy_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_UNMAP_NOTIFY:
|
case XCB_UNMAP_NOTIFY:
|
||||||
/* UnmapNotify is received when a tray client hides its window. */
|
/* UnmapNotify is received when a tray client hides its window. */
|
||||||
handle_unmap_notify((xcb_unmap_notify_event_t*) event);
|
handle_unmap_notify((xcb_unmap_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_MAP_NOTIFY:
|
case XCB_MAP_NOTIFY:
|
||||||
handle_map_notify((xcb_map_notify_event_t*) event);
|
handle_map_notify((xcb_map_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_PROPERTY_NOTIFY:
|
case XCB_PROPERTY_NOTIFY:
|
||||||
/* PropertyNotify */
|
/* PropertyNotify */
|
||||||
handle_property_notify((xcb_property_notify_event_t*) event);
|
handle_property_notify((xcb_property_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_CONFIGURE_REQUEST:
|
case XCB_CONFIGURE_REQUEST:
|
||||||
/* ConfigureRequest, sent by a tray child */
|
/* ConfigureRequest, sent by a tray child */
|
||||||
handle_configure_request((xcb_configure_request_event_t*) event);
|
handle_configure_request((xcb_configure_request_event_t *)event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(event);
|
free(event);
|
||||||
@ -910,7 +911,7 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
DLOG("Got XKB-Event!\n");
|
DLOG("Got XKB-Event!\n");
|
||||||
|
|
||||||
while (XPending(xkb_dpy)) {
|
while (XPending(xkb_dpy)) {
|
||||||
XNextEvent(xkb_dpy, (XEvent*)&ev);
|
XNextEvent(xkb_dpy, (XEvent *)&ev);
|
||||||
|
|
||||||
if (ev.type != xkb_event_base) {
|
if (ev.type != xkb_event_base) {
|
||||||
ELOG("No Xkb-Event!\n");
|
ELOG("No Xkb-Event!\n");
|
||||||
@ -926,31 +927,31 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
modstate = mods & config.modifier;
|
modstate = mods & config.modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DLOGMOD(modmask, status) \
|
#define DLOGMOD(modmask, status) \
|
||||||
do { \
|
do { \
|
||||||
switch (modmask) { \
|
switch (modmask) { \
|
||||||
case ShiftMask: \
|
case ShiftMask: \
|
||||||
DLOG("ShiftMask got " #status "!\n"); \
|
DLOG("ShiftMask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case ControlMask: \
|
case ControlMask: \
|
||||||
DLOG("ControlMask got " #status "!\n"); \
|
DLOG("ControlMask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod1Mask: \
|
case Mod1Mask: \
|
||||||
DLOG("Mod1Mask got " #status "!\n"); \
|
DLOG("Mod1Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod2Mask: \
|
case Mod2Mask: \
|
||||||
DLOG("Mod2Mask got " #status "!\n"); \
|
DLOG("Mod2Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod3Mask: \
|
case Mod3Mask: \
|
||||||
DLOG("Mod3Mask got " #status "!\n"); \
|
DLOG("Mod3Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod4Mask: \
|
case Mod4Mask: \
|
||||||
DLOG("Mod4Mask got " #status "!\n"); \
|
DLOG("Mod4Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod5Mask: \
|
case Mod5Mask: \
|
||||||
DLOG("Mod5Mask got " #status "!\n"); \
|
DLOG("Mod5Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
if (modstate != mod_pressed) {
|
if (modstate != mod_pressed) {
|
||||||
@ -984,9 +985,9 @@ char *init_xcb_early() {
|
|||||||
conn = xcb_connection;
|
conn = xcb_connection;
|
||||||
DLOG("Connected to xcb\n");
|
DLOG("Connected to xcb\n");
|
||||||
|
|
||||||
/* We have to request the atoms we need */
|
/* We have to request the atoms we need */
|
||||||
#define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
|
#define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(xcb_connection, screen);
|
root_screen = xcb_aux_get_screen(xcb_connection, screen);
|
||||||
xcb_root = root_screen->root;
|
xcb_root = root_screen->root;
|
||||||
@ -994,7 +995,7 @@ char *init_xcb_early() {
|
|||||||
/* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
|
/* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
|
||||||
* this way, we can choose to crop it */
|
* this way, we can choose to crop it */
|
||||||
uint32_t mask = XCB_GC_FOREGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND;
|
||||||
uint32_t vals[] = { colors.bar_bg, colors.bar_bg };
|
uint32_t vals[] = {colors.bar_bg, colors.bar_bg};
|
||||||
|
|
||||||
statusline_clear = xcb_generate_id(xcb_connection);
|
statusline_clear = xcb_generate_id(xcb_connection);
|
||||||
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
||||||
@ -1018,7 +1019,6 @@ char *init_xcb_early() {
|
|||||||
root_screen->width_in_pixels,
|
root_screen->width_in_pixels,
|
||||||
root_screen->height_in_pixels);
|
root_screen->height_in_pixels);
|
||||||
|
|
||||||
|
|
||||||
/* The various Watchers to communicate with xcb */
|
/* The various Watchers to communicate with xcb */
|
||||||
xcb_io = smalloc(sizeof(ev_io));
|
xcb_io = smalloc(sizeof(ev_io));
|
||||||
xcb_prep = smalloc(sizeof(ev_prepare));
|
xcb_prep = smalloc(sizeof(ev_prepare));
|
||||||
@ -1099,7 +1099,7 @@ void register_xkb_keyevents() {
|
|||||||
*/
|
*/
|
||||||
void deregister_xkb_keyevents() {
|
void deregister_xkb_keyevents() {
|
||||||
if (xkb_dpy != NULL) {
|
if (xkb_dpy != NULL) {
|
||||||
ev_io_stop (main_loop, xkb_io);
|
ev_io_stop(main_loop, xkb_io);
|
||||||
XCloseDisplay(xkb_dpy);
|
XCloseDisplay(xkb_dpy);
|
||||||
close(xkb_io->fd);
|
close(xkb_io->fd);
|
||||||
FREE(xkb_io);
|
FREE(xkb_io);
|
||||||
@ -1134,8 +1134,8 @@ void init_xcb_late(char *fontname) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void send_tray_clientmessage(void) {
|
static void send_tray_clientmessage(void) {
|
||||||
uint8_t buffer[32] = { 0 };
|
uint8_t buffer[32] = {0};
|
||||||
xcb_client_message_event_t *ev = (xcb_client_message_event_t*)buffer;
|
xcb_client_message_event_t *ev = (xcb_client_message_event_t *)buffer;
|
||||||
|
|
||||||
ev->response_type = XCB_CLIENT_MESSAGE;
|
ev->response_type = XCB_CLIENT_MESSAGE;
|
||||||
ev->window = xcb_root;
|
ev->window = xcb_root;
|
||||||
@ -1149,10 +1149,9 @@ static void send_tray_clientmessage(void) {
|
|||||||
0,
|
0,
|
||||||
xcb_root,
|
xcb_root,
|
||||||
0xFFFFFF,
|
0xFFFFFF,
|
||||||
(char*)buffer);
|
(char *)buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
||||||
* for the X11 display we are running on, then acquiring the selection for this
|
* for the X11 display we are running on, then acquiring the selection for this
|
||||||
@ -1171,7 +1170,7 @@ void init_tray(void) {
|
|||||||
/* tray support: we need a window to own the selection */
|
/* tray support: we need a window to own the selection */
|
||||||
selwin = xcb_generate_id(xcb_connection);
|
selwin = xcb_generate_id(xcb_connection);
|
||||||
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
||||||
uint32_t selval[] = { 1 };
|
uint32_t selval[] = {1};
|
||||||
xcb_create_window(xcb_connection,
|
xcb_create_window(xcb_connection,
|
||||||
root_screen->root_depth,
|
root_screen->root_depth,
|
||||||
selwin,
|
selwin,
|
||||||
@ -1220,8 +1219,9 @@ void init_tray(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selreply->owner != selwin) {
|
if (selreply->owner != selwin) {
|
||||||
ELOG("Could not set the %s selection. " \
|
ELOG("Could not set the %s selection. "
|
||||||
"Maybe another tray is already running?\n", atomname);
|
"Maybe another tray is already running?\n",
|
||||||
|
atomname);
|
||||||
/* NOTE that this error is not fatal. We just can’t provide tray
|
/* NOTE that this error is not fatal. We just can’t provide tray
|
||||||
* functionality */
|
* functionality */
|
||||||
free(selreply);
|
free(selreply);
|
||||||
@ -1280,7 +1280,7 @@ void init_tray_colors(void) {
|
|||||||
void clean_xcb(void) {
|
void clean_xcb(void) {
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
free_workspaces();
|
free_workspaces();
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
destroy_window(o_walk);
|
destroy_window(o_walk);
|
||||||
FREE(o_walk->trayclients);
|
FREE(o_walk->trayclients);
|
||||||
FREE(o_walk->workspaces);
|
FREE(o_walk->workspaces);
|
||||||
@ -1307,15 +1307,16 @@ void clean_xcb(void) {
|
|||||||
*/
|
*/
|
||||||
void get_atoms(void) {
|
void get_atoms(void) {
|
||||||
xcb_intern_atom_reply_t *reply;
|
xcb_intern_atom_reply_t *reply;
|
||||||
#define ATOM_DO(name) reply = xcb_intern_atom_reply(xcb_connection, atom_cookies[name], NULL); \
|
#define ATOM_DO(name) \
|
||||||
if (reply == NULL) { \
|
reply = xcb_intern_atom_reply(xcb_connection, atom_cookies[name], NULL); \
|
||||||
ELOG("Could not get atom %s\n", #name); \
|
if (reply == NULL) { \
|
||||||
exit(EXIT_FAILURE); \
|
ELOG("Could not get atom %s\n", #name); \
|
||||||
} \
|
exit(EXIT_FAILURE); \
|
||||||
atoms[name] = reply->atom; \
|
} \
|
||||||
free(reply);
|
atoms[name] = reply->atom; \
|
||||||
|
free(reply);
|
||||||
|
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
DLOG("Got Atoms\n");
|
DLOG("Got Atoms\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,14 +1352,14 @@ void kick_tray_clients(i3_output *output) {
|
|||||||
/* Fake a DestroyNotify so that Qt re-adds tray icons.
|
/* Fake a DestroyNotify so that Qt re-adds tray icons.
|
||||||
* We cannot actually destroy the window because then Qt will not restore
|
* We cannot actually destroy the window because then Qt will not restore
|
||||||
* its event mask on the new window. */
|
* its event mask on the new window. */
|
||||||
uint8_t buffer[32] = { 0 };
|
uint8_t buffer[32] = {0};
|
||||||
xcb_destroy_notify_event_t *event = (xcb_destroy_notify_event_t*)buffer;
|
xcb_destroy_notify_event_t *event = (xcb_destroy_notify_event_t *)buffer;
|
||||||
|
|
||||||
event->response_type = XCB_DESTROY_NOTIFY;
|
event->response_type = XCB_DESTROY_NOTIFY;
|
||||||
event->event = selwin;
|
event->event = selwin;
|
||||||
event->window = selwin;
|
event->window = selwin;
|
||||||
|
|
||||||
xcb_send_event(conn, false, selwin, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)event);
|
xcb_send_event(conn, false, selwin, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *)event);
|
||||||
|
|
||||||
send_tray_clientmessage();
|
send_tray_clientmessage();
|
||||||
}
|
}
|
||||||
@ -1397,7 +1398,7 @@ void realloc_sl_buffer(void) {
|
|||||||
bar_height);
|
bar_height);
|
||||||
|
|
||||||
uint32_t mask = XCB_GC_FOREGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND;
|
||||||
uint32_t vals[2] = { colors.bar_bg, colors.bar_bg };
|
uint32_t vals[2] = {colors.bar_bg, colors.bar_bg};
|
||||||
xcb_free_gc(xcb_connection, statusline_clear);
|
xcb_free_gc(xcb_connection, statusline_clear);
|
||||||
statusline_clear = xcb_generate_id(xcb_connection);
|
statusline_clear = xcb_generate_id(xcb_connection);
|
||||||
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
||||||
@ -1421,7 +1422,6 @@ void realloc_sl_buffer(void) {
|
|||||||
xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) {
|
xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1434,7 +1434,7 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
static bool tray_configured = false;
|
static bool tray_configured = false;
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active) {
|
if (!walk->active) {
|
||||||
/* If an output is not active, we destroy its bar */
|
/* If an output is not active, we destroy its bar */
|
||||||
/* FIXME: Maybe we rather want to unmap? */
|
/* FIXME: Maybe we rather want to unmap? */
|
||||||
@ -1517,7 +1517,7 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
XCB_ATOM_ATOM,
|
XCB_ATOM_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
(unsigned char *)&atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
||||||
|
|
||||||
/* We need to tell i3, where to reserve space for i3bar */
|
/* We need to tell i3, where to reserve space for i3bar */
|
||||||
/* left, right, top, bottom, left_start_y, left_end_y,
|
/* left, right, top, bottom, left_start_y, left_end_y,
|
||||||
@ -1578,13 +1578,13 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
|
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xcb_request_failed(win_cookie, "Could not create window") ||
|
if (xcb_request_failed(win_cookie, "Could not create window") ||
|
||||||
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
||||||
xcb_request_failed(dock_cookie, "Could not set dock mode") ||
|
xcb_request_failed(dock_cookie, "Could not set dock mode") ||
|
||||||
xcb_request_failed(class_cookie, "Could not set WM_CLASS") ||
|
xcb_request_failed(class_cookie, "Could not set WM_CLASS") ||
|
||||||
xcb_request_failed(name_cookie, "Could not set WM_NAME") ||
|
xcb_request_failed(name_cookie, "Could not set WM_NAME") ||
|
||||||
xcb_request_failed(strut_cookie, "Could not set strut") ||
|
xcb_request_failed(strut_cookie, "Could not set strut") ||
|
||||||
xcb_request_failed(gc_cookie, "Could not create graphical context") ||
|
xcb_request_failed(gc_cookie, "Could not create graphical context") ||
|
||||||
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
|
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -1596,9 +1596,9 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
* VGA-1 but output == [HDMI-1]).
|
* VGA-1 but output == [HDMI-1]).
|
||||||
*/
|
*/
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (strcasecmp(output->name, tray_output) == 0 ||
|
if (strcasecmp(output->name, tray_output) == 0 ||
|
||||||
(strcasecmp(tray_output, "primary") == 0 && output->primary)) {
|
(strcasecmp(tray_output, "primary") == 0 && output->primary)) {
|
||||||
init_tray();
|
init_tray();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1665,9 +1665,9 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
|
|
||||||
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") ||
|
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") ||
|
||||||
xcb_request_failed(chg_cookie, "Could not change window") ||
|
xcb_request_failed(chg_cookie, "Could not change window") ||
|
||||||
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
||||||
(redraw_bars && (xcb_request_failed(umap_cookie, "Could not unmap window") ||
|
(redraw_bars && (xcb_request_failed(umap_cookie, "Could not unmap window") ||
|
||||||
(config.hide_on_modifier == M_DOCK && xcb_request_failed(map_cookie, "Could not map window"))))) {
|
(config.hide_on_modifier == M_DOCK && xcb_request_failed(map_cookie, "Could not map window"))))) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1685,7 +1685,7 @@ void draw_bars(bool unhide) {
|
|||||||
refresh_statusline();
|
refresh_statusline();
|
||||||
|
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (!outputs_walk->active) {
|
if (!outputs_walk->active) {
|
||||||
DLOG("Output %s inactive, skipping...\n", outputs_walk->name);
|
DLOG("Output %s inactive, skipping...\n", outputs_walk->name);
|
||||||
continue;
|
continue;
|
||||||
@ -1700,7 +1700,7 @@ void draw_bars(bool unhide) {
|
|||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
XCB_GC_FOREGROUND,
|
XCB_GC_FOREGROUND,
|
||||||
&color);
|
&color);
|
||||||
xcb_rectangle_t rect = { 0, 0, outputs_walk->rect.w, bar_height };
|
xcb_rectangle_t rect = {0, 0, outputs_walk->rect.w, bar_height};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1715,7 +1715,7 @@ void draw_bars(bool unhide) {
|
|||||||
* position */
|
* position */
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
int traypx = 0;
|
int traypx = 0;
|
||||||
TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, outputs_walk->trayclients, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
/* We assume the tray icons are quadratic (we use the font
|
/* We assume the tray icons are quadratic (we use the font
|
||||||
@ -1737,7 +1737,7 @@ void draw_bars(bool unhide) {
|
|||||||
|
|
||||||
if (!config.disable_ws) {
|
if (!config.disable_ws) {
|
||||||
i3_ws *ws_walk;
|
i3_ws *ws_walk;
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
DLOG("Drawing Button for WS %s at x = %d, len = %d\n",
|
DLOG("Drawing Button for WS %s at x = %d, len = %d\n",
|
||||||
i3string_as_utf8(ws_walk->name), i, ws_walk->name_width);
|
i3string_as_utf8(ws_walk->name), i, ws_walk->name_width);
|
||||||
uint32_t fg_color = colors.inactive_ws_fg;
|
uint32_t fg_color = colors.inactive_ws_fg;
|
||||||
@ -1762,29 +1762,29 @@ void draw_bars(bool unhide) {
|
|||||||
unhide = true;
|
unhide = true;
|
||||||
}
|
}
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
||||||
uint32_t vals_border[] = { border_color, border_color };
|
uint32_t vals_border[] = {border_color, border_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals_border);
|
vals_border);
|
||||||
xcb_rectangle_t rect_border = { i,
|
xcb_rectangle_t rect_border = {i,
|
||||||
logical_px(1),
|
logical_px(1),
|
||||||
ws_walk->name_width + logical_px(10),
|
ws_walk->name_width + logical_px(10),
|
||||||
font.height + logical_px(4) };
|
font.height + logical_px(4)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
1,
|
1,
|
||||||
&rect_border);
|
&rect_border);
|
||||||
uint32_t vals[] = { bg_color, bg_color };
|
uint32_t vals[] = {bg_color, bg_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals);
|
vals);
|
||||||
xcb_rectangle_t rect = { i + logical_px(1),
|
xcb_rectangle_t rect = {i + logical_px(1),
|
||||||
2 * logical_px(1),
|
2 * logical_px(1),
|
||||||
ws_walk->name_width + logical_px(8),
|
ws_walk->name_width + logical_px(8),
|
||||||
font.height + logical_px(2) };
|
font.height + logical_px(2)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1794,7 +1794,6 @@ void draw_bars(bool unhide) {
|
|||||||
draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc,
|
draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc,
|
||||||
i + logical_px(5), 3 * logical_px(1), ws_walk->name_width);
|
i + logical_px(5), 3 * logical_px(1), ws_walk->name_width);
|
||||||
i += logical_px(10) + ws_walk->name_width + logical_px(1);
|
i += logical_px(10) + ws_walk->name_width + logical_px(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1803,24 +1802,24 @@ void draw_bars(bool unhide) {
|
|||||||
uint32_t bg_color = colors.urgent_ws_bg;
|
uint32_t bg_color = colors.urgent_ws_bg;
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
||||||
|
|
||||||
uint32_t vals_border[] = { colors.urgent_ws_border, colors.urgent_ws_border };
|
uint32_t vals_border[] = {colors.urgent_ws_border, colors.urgent_ws_border};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals_border);
|
vals_border);
|
||||||
xcb_rectangle_t rect_border = { i, 1, binding.width + 10, font.height + 4 };
|
xcb_rectangle_t rect_border = {i, 1, binding.width + 10, font.height + 4};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
1,
|
1,
|
||||||
&rect_border);
|
&rect_border);
|
||||||
|
|
||||||
uint32_t vals[] = { bg_color, bg_color };
|
uint32_t vals[] = {bg_color, bg_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals);
|
vals);
|
||||||
xcb_rectangle_t rect = { i + 1, 2, binding.width + 8, font.height + 2 };
|
xcb_rectangle_t rect = {i + 1, 2, binding.width + 8, font.height + 2};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1838,8 +1837,8 @@ void draw_bars(bool unhide) {
|
|||||||
|
|
||||||
/* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */
|
/* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */
|
||||||
if (mod_pressed ||
|
if (mod_pressed ||
|
||||||
config.hidden_state == S_SHOW ||
|
config.hidden_state == S_SHOW ||
|
||||||
unhide) {
|
unhide) {
|
||||||
unhide_bars();
|
unhide_bars();
|
||||||
} else if (config.hide_on_modifier == M_HIDE) {
|
} else if (config.hide_on_modifier == M_HIDE) {
|
||||||
hide_bars();
|
hide_bars();
|
||||||
@ -1854,7 +1853,7 @@ void draw_bars(bool unhide) {
|
|||||||
*/
|
*/
|
||||||
void redraw_bars(void) {
|
void redraw_bars(void) {
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (!outputs_walk->active) {
|
if (!outputs_walk->active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -12,5 +12,5 @@ extern xcb_screen_t *root_screen;
|
|||||||
int logical_px(const int logical) {
|
int logical_px(const int logical) {
|
||||||
const int dpi = (double)root_screen->height_in_pixels * 25.4 /
|
const int dpi = (double)root_screen->height_in_pixels * 25.4 /
|
||||||
(double)root_screen->height_in_millimeters;
|
(double)root_screen->height_in_millimeters;
|
||||||
return ceil((dpi / 96.0) * logical);
|
return ceil((dpi / 96.0) * logical);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ void fake_configure_notify(xcb_connection_t *conn, xcb_rectangle_t r, xcb_window
|
|||||||
generated_event->above_sibling = XCB_NONE;
|
generated_event->above_sibling = XCB_NONE;
|
||||||
generated_event->override_redirect = false;
|
generated_event->override_redirect = false;
|
||||||
|
|
||||||
xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)generated_event);
|
xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *)generated_event);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
|
|
||||||
free(event);
|
free(event);
|
||||||
|
43
libi3/font.c
43
libi3/font.c
@ -69,8 +69,7 @@ static bool load_pango_font(i3Font *font, const char *desc) {
|
|||||||
|
|
||||||
LOG("Using Pango font %s, size %d\n",
|
LOG("Using Pango font %s, size %d\n",
|
||||||
pango_font_description_get_family(font->specific.pango_desc),
|
pango_font_description_get_family(font->specific.pango_desc),
|
||||||
pango_font_description_get_size(font->specific.pango_desc) / PANGO_SCALE
|
pango_font_description_get_size(font->specific.pango_desc) / PANGO_SCALE);
|
||||||
);
|
|
||||||
|
|
||||||
/* We cache root_visual_type here, since you must call
|
/* We cache root_visual_type here, since you must call
|
||||||
* load_pango_font before any other pango function
|
* load_pango_font before any other pango function
|
||||||
@ -103,11 +102,11 @@ static bool load_pango_font(i3Font *font, const char *desc) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void draw_text_pango(const char *text, size_t text_len,
|
static void draw_text_pango(const char *text, size_t text_len,
|
||||||
xcb_drawable_t drawable, int x, int y, int max_width) {
|
xcb_drawable_t drawable, int x, int y, int max_width) {
|
||||||
/* Create the Pango layout */
|
/* Create the Pango layout */
|
||||||
/* root_visual_type is cached in load_pango_font */
|
/* root_visual_type is cached in load_pango_font */
|
||||||
cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable,
|
cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable,
|
||||||
root_visual_type, x + max_width, y + savedFont->height);
|
root_visual_type, x + max_width, y + savedFont->height);
|
||||||
cairo_t *cr = cairo_create(surface);
|
cairo_t *cr = cairo_create(surface);
|
||||||
PangoLayout *layout = create_layout_with_dpi(cr);
|
PangoLayout *layout = create_layout_with_dpi(cr);
|
||||||
gint height;
|
gint height;
|
||||||
@ -188,7 +187,7 @@ i3Font load_font(const char *pattern, const bool fallback) {
|
|||||||
/* Send all our requests first */
|
/* Send all our requests first */
|
||||||
font.specific.xcb.id = xcb_generate_id(conn);
|
font.specific.xcb.id = xcb_generate_id(conn);
|
||||||
xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
||||||
strlen(pattern), pattern);
|
strlen(pattern), pattern);
|
||||||
xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
||||||
|
|
||||||
/* Check for errors. If errors, fall back to default font. */
|
/* Check for errors. If errors, fall back to default font. */
|
||||||
@ -201,7 +200,7 @@ i3Font load_font(const char *pattern, const bool fallback) {
|
|||||||
pattern, error->error_code);
|
pattern, error->error_code);
|
||||||
pattern = "fixed";
|
pattern = "fixed";
|
||||||
font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
||||||
strlen(pattern), pattern);
|
strlen(pattern), pattern);
|
||||||
info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
||||||
|
|
||||||
/* Check if we managed to open 'fixed' */
|
/* Check if we managed to open 'fixed' */
|
||||||
@ -212,12 +211,13 @@ i3Font load_font(const char *pattern, const bool fallback) {
|
|||||||
ELOG("Could not open fallback font 'fixed', trying with '-misc-*'.\n");
|
ELOG("Could not open fallback font 'fixed', trying with '-misc-*'.\n");
|
||||||
pattern = "-misc-*";
|
pattern = "-misc-*";
|
||||||
font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
|
||||||
strlen(pattern), pattern);
|
strlen(pattern), pattern);
|
||||||
info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
info_cookie = xcb_query_font(conn, font.specific.xcb.id);
|
||||||
|
|
||||||
if ((error = xcb_request_check(conn, font_cookie)) != NULL)
|
if ((error = xcb_request_check(conn, font_cookie)) != NULL)
|
||||||
errx(EXIT_FAILURE, "Could open neither requested font nor fallbacks "
|
errx(EXIT_FAILURE, "Could open neither requested font nor fallbacks "
|
||||||
"(fixed or -misc-*): X11 error %d", error->error_code);
|
"(fixed or -misc-*): X11 error %d",
|
||||||
|
error->error_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background
|
|||||||
case FONT_TYPE_XCB: {
|
case FONT_TYPE_XCB: {
|
||||||
/* Change the font and colors in the GC */
|
/* Change the font and colors in the GC */
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
|
||||||
uint32_t values[] = { foreground, background, savedFont->specific.xcb.id };
|
uint32_t values[] = {foreground, background, savedFont->specific.xcb.id};
|
||||||
xcb_change_gc(conn, gc, mask, values);
|
xcb_change_gc(conn, gc, mask, values);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -314,7 +314,7 @@ void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background
|
|||||||
static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len);
|
static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len);
|
||||||
|
|
||||||
static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawable_t drawable,
|
static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawable_t drawable,
|
||||||
xcb_gcontext_t gc, int x, int y, int max_width) {
|
xcb_gcontext_t gc, int x, int y, int max_width) {
|
||||||
/* X11 coordinates for fonts start at the baseline */
|
/* X11 coordinates for fonts start at the baseline */
|
||||||
int pos_y = y + savedFont->specific.xcb.info->font_ascent;
|
int pos_y = y + savedFont->specific.xcb.info->font_ascent;
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ void draw_text(i3String *text, xcb_drawable_t drawable,
|
|||||||
return;
|
return;
|
||||||
case FONT_TYPE_XCB:
|
case FONT_TYPE_XCB:
|
||||||
draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text),
|
draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text),
|
||||||
drawable, gc, x, y, max_width);
|
drawable, gc, x, y, max_width);
|
||||||
break;
|
break;
|
||||||
#if PANGO_SUPPORT
|
#if PANGO_SUPPORT
|
||||||
case FONT_TYPE_PANGO:
|
case FONT_TYPE_PANGO:
|
||||||
@ -379,15 +379,14 @@ void draw_text(i3String *text, xcb_drawable_t drawable,
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void draw_text_ascii(const char *text, xcb_drawable_t drawable,
|
void draw_text_ascii(const char *text, xcb_drawable_t drawable,
|
||||||
xcb_gcontext_t gc, int x, int y, int max_width) {
|
xcb_gcontext_t gc, int x, int y, int max_width) {
|
||||||
assert(savedFont != NULL);
|
assert(savedFont != NULL);
|
||||||
|
|
||||||
switch (savedFont->type) {
|
switch (savedFont->type) {
|
||||||
case FONT_TYPE_NONE:
|
case FONT_TYPE_NONE:
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
return;
|
return;
|
||||||
case FONT_TYPE_XCB:
|
case FONT_TYPE_XCB: {
|
||||||
{
|
|
||||||
size_t text_len = strlen(text);
|
size_t text_len = strlen(text);
|
||||||
if (text_len > 255) {
|
if (text_len > 255) {
|
||||||
/* The text is too long to draw it directly to X */
|
/* The text is too long to draw it directly to X */
|
||||||
@ -425,9 +424,9 @@ static int xcb_query_text_width(const xcb_char2b_t *text, size_t text_len) {
|
|||||||
/* Query the text width */
|
/* Query the text width */
|
||||||
xcb_generic_error_t *error;
|
xcb_generic_error_t *error;
|
||||||
xcb_query_text_extents_cookie_t cookie = xcb_query_text_extents(conn,
|
xcb_query_text_extents_cookie_t cookie = xcb_query_text_extents(conn,
|
||||||
savedFont->specific.xcb.id, text_len, (xcb_char2b_t*)text);
|
savedFont->specific.xcb.id, text_len, (xcb_char2b_t *)text);
|
||||||
xcb_query_text_extents_reply_t *reply = xcb_query_text_extents_reply(conn,
|
xcb_query_text_extents_reply_t *reply = xcb_query_text_extents_reply(conn,
|
||||||
cookie, &error);
|
cookie, &error);
|
||||||
if (reply == NULL) {
|
if (reply == NULL) {
|
||||||
/* We return a safe estimate because a rendering error is better than
|
/* We return a safe estimate because a rendering error is better than
|
||||||
* a crash. Plus, the user will see the error in his log. */
|
* a crash. Plus, the user will see the error in his log. */
|
||||||
@ -469,14 +468,14 @@ static int predict_text_width_xcb(const xcb_char2b_t *input, size_t text_len) {
|
|||||||
|
|
||||||
/* Don't you ask me, how this one works… (Merovius) */
|
/* Don't you ask me, how this one works… (Merovius) */
|
||||||
info = &font_table[((row - font_info->min_byte1) *
|
info = &font_table[((row - font_info->min_byte1) *
|
||||||
(font_info->max_char_or_byte2 - font_info->min_char_or_byte2 + 1)) +
|
(font_info->max_char_or_byte2 - font_info->min_char_or_byte2 + 1)) +
|
||||||
(col - font_info->min_char_or_byte2)];
|
(col - font_info->min_char_or_byte2)];
|
||||||
|
|
||||||
if (info->character_width != 0 ||
|
if (info->character_width != 0 ||
|
||||||
(info->right_side_bearing |
|
(info->right_side_bearing |
|
||||||
info->left_side_bearing |
|
info->left_side_bearing |
|
||||||
info->ascent |
|
info->ascent |
|
||||||
info->descent) != 0) {
|
info->descent) != 0) {
|
||||||
width += info->character_width;
|
width += info->character_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,87 +15,86 @@
|
|||||||
* Returned value must be freed by the caller.
|
* Returned value must be freed by the caller.
|
||||||
*/
|
*/
|
||||||
char *get_exe_path(const char *argv0) {
|
char *get_exe_path(const char *argv0) {
|
||||||
size_t destpath_size = 1024;
|
size_t destpath_size = 1024;
|
||||||
size_t tmp_size = 1024;
|
size_t tmp_size = 1024;
|
||||||
char *destpath = smalloc(destpath_size);
|
char *destpath = smalloc(destpath_size);
|
||||||
char *tmp = smalloc(tmp_size);
|
char *tmp = smalloc(tmp_size);
|
||||||
|
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
/* Linux and Debian/kFreeBSD provide /proc/self/exe */
|
/* Linux and Debian/kFreeBSD provide /proc/self/exe */
|
||||||
#if defined(__linux__) || defined(__FreeBSD_kernel__)
|
#if defined(__linux__) || defined(__FreeBSD_kernel__)
|
||||||
const char *exepath = "/proc/self/exe";
|
const char *exepath = "/proc/self/exe";
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
const char *exepath = "/proc/curproc/file";
|
const char *exepath = "/proc/curproc/file";
|
||||||
#endif
|
#endif
|
||||||
ssize_t linksize;
|
ssize_t linksize;
|
||||||
|
|
||||||
while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
|
while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
|
||||||
destpath_size = destpath_size * 2;
|
destpath_size = destpath_size * 2;
|
||||||
destpath = srealloc(destpath, destpath_size);
|
destpath = srealloc(destpath, destpath_size);
|
||||||
}
|
}
|
||||||
if (linksize != -1) {
|
if (linksize != -1) {
|
||||||
/* readlink() does not NULL-terminate strings, so we have to. */
|
/* readlink() does not NULL-terminate strings, so we have to. */
|
||||||
destpath[linksize] = '\0';
|
destpath[linksize] = '\0';
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return destpath;
|
return destpath;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* argv[0] is most likely a full path if it starts with a slash. */
|
/* argv[0] is most likely a full path if it starts with a slash. */
|
||||||
if (argv0[0] == '/') {
|
if (argv0[0] == '/') {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
free(destpath);
|
free(destpath);
|
||||||
return sstrdup(argv0);
|
return sstrdup(argv0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if argv[0] contains a /, prepend the working directory */
|
/* if argv[0] contains a /, prepend the working directory */
|
||||||
if (strchr(argv0, '/') != NULL) {
|
if (strchr(argv0, '/') != NULL) {
|
||||||
char *retgcwd;
|
char *retgcwd;
|
||||||
while ((retgcwd = getcwd(tmp, tmp_size)) == NULL && errno == ERANGE) {
|
while ((retgcwd = getcwd(tmp, tmp_size)) == NULL && errno == ERANGE) {
|
||||||
tmp_size = tmp_size * 2;
|
tmp_size = tmp_size * 2;
|
||||||
tmp = srealloc(tmp, tmp_size);
|
tmp = srealloc(tmp, tmp_size);
|
||||||
}
|
}
|
||||||
if (retgcwd != NULL) {
|
if (retgcwd != NULL) {
|
||||||
free(destpath);
|
free(destpath);
|
||||||
sasprintf(&destpath, "%s/%s", tmp, argv0);
|
sasprintf(&destpath, "%s/%s", tmp, argv0);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return destpath;
|
return destpath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fall back to searching $PATH (or _CS_PATH in absence of $PATH). */
|
/* Fall back to searching $PATH (or _CS_PATH in absence of $PATH). */
|
||||||
char *path = getenv("PATH");
|
char *path = getenv("PATH");
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
/* _CS_PATH is typically something like "/bin:/usr/bin" */
|
/* _CS_PATH is typically something like "/bin:/usr/bin" */
|
||||||
while (confstr(_CS_PATH, tmp, tmp_size) > tmp_size) {
|
while (confstr(_CS_PATH, tmp, tmp_size) > tmp_size) {
|
||||||
tmp_size = tmp_size * 2;
|
tmp_size = tmp_size * 2;
|
||||||
tmp = srealloc(tmp, tmp_size);
|
tmp = srealloc(tmp, tmp_size);
|
||||||
}
|
}
|
||||||
sasprintf(&path, ":%s", tmp);
|
sasprintf(&path, ":%s", tmp);
|
||||||
} else {
|
} else {
|
||||||
path = strdup(path);
|
path = strdup(path);
|
||||||
}
|
}
|
||||||
const char *component;
|
const char *component;
|
||||||
char *str = path;
|
char *str = path;
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((component = strtok(str, ":")) == NULL)
|
if ((component = strtok(str, ":")) == NULL)
|
||||||
break;
|
break;
|
||||||
str = NULL;
|
str = NULL;
|
||||||
free(destpath);
|
free(destpath);
|
||||||
sasprintf(&destpath, "%s/%s", component, argv0);
|
sasprintf(&destpath, "%s/%s", component, argv0);
|
||||||
/* Of course this is not 100% equivalent to actually exec()ing the
|
/* Of course this is not 100% equivalent to actually exec()ing the
|
||||||
* binary, but meh. */
|
* binary, but meh. */
|
||||||
if (access(destpath, X_OK) == 0) {
|
if (access(destpath, X_OK) == 0) {
|
||||||
free(path);
|
free(path);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return destpath;
|
return destpath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(destpath);
|
free(destpath);
|
||||||
free(path);
|
free(path);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
/* Last resort: maybe it’s in /usr/bin? */
|
/* Last resort: maybe it’s in /usr/bin? */
|
||||||
return sstrdup("/usr/bin/i3-nagbar");
|
return sstrdup("/usr/bin/i3-nagbar");
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ uint32_t aio_get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint32_t get_mod_mask_for(uint32_t keysym,
|
uint32_t get_mod_mask_for(uint32_t keysym,
|
||||||
xcb_key_symbols_t *symbols,
|
xcb_key_symbols_t *symbols,
|
||||||
xcb_get_modifier_mapping_reply_t *modmap_reply) {
|
xcb_get_modifier_mapping_reply_t *modmap_reply) {
|
||||||
xcb_keycode_t *codes, *modmap;
|
xcb_keycode_t *codes, *modmap;
|
||||||
xcb_keycode_t mod_code;
|
xcb_keycode_t mod_code;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ int ipc_connect(const char *socket_path) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
err(EXIT_FAILURE, "Could not connect to i3");
|
err(EXIT_FAILURE, "Could not connect to i3");
|
||||||
|
|
||||||
return sockfd;
|
return sockfd;
|
||||||
|
@ -28,10 +28,9 @@ int ipc_send_message(int sockfd, const uint32_t message_size,
|
|||||||
const uint32_t message_type, const uint8_t *payload) {
|
const uint32_t message_type, const uint8_t *payload) {
|
||||||
const i3_ipc_header_t header = {
|
const i3_ipc_header_t header = {
|
||||||
/* We don’t use I3_IPC_MAGIC because it’s a 0-terminated C string. */
|
/* We don’t use I3_IPC_MAGIC because it’s a 0-terminated C string. */
|
||||||
.magic = { 'i', '3', '-', 'i', 'p', 'c' },
|
.magic = {'i', '3', '-', 'i', 'p', 'c'},
|
||||||
.size = message_size,
|
.size = message_size,
|
||||||
.type = message_type
|
.type = message_type};
|
||||||
};
|
|
||||||
|
|
||||||
size_t sent_bytes = 0;
|
size_t sent_bytes = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -40,7 +39,7 @@ int ipc_send_message(int sockfd, const uint32_t message_size,
|
|||||||
* buffers which cannot fit 14 bytes into them, so the write() will only be
|
* buffers which cannot fit 14 bytes into them, so the write() will only be
|
||||||
* called once. */
|
* called once. */
|
||||||
while (sent_bytes < sizeof(i3_ipc_header_t)) {
|
while (sent_bytes < sizeof(i3_ipc_header_t)) {
|
||||||
if ((n = write(sockfd, ((void*)&header) + sent_bytes, sizeof(i3_ipc_header_t) - sent_bytes)) == -1) {
|
if ((n = write(sockfd, ((void *)&header) + sent_bytes, sizeof(i3_ipc_header_t) - sent_bytes)) == -1) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
continue;
|
continue;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -80,14 +80,14 @@ char *root_atom_contents(const char *atomname, xcb_connection_t *provided_conn,
|
|||||||
if (prop_reply->type == XCB_ATOM_CARDINAL) {
|
if (prop_reply->type == XCB_ATOM_CARDINAL) {
|
||||||
/* We treat a CARDINAL as a >= 32-bit unsigned int. The only CARDINAL
|
/* We treat a CARDINAL as a >= 32-bit unsigned int. The only CARDINAL
|
||||||
* we query is I3_PID, which is 32-bit. */
|
* we query is I3_PID, which is 32-bit. */
|
||||||
if (asprintf(&content, "%u", *((unsigned int*)xcb_get_property_value(prop_reply))) == -1) {
|
if (asprintf(&content, "%u", *((unsigned int *)xcb_get_property_value(prop_reply))) == -1) {
|
||||||
free(atom_reply);
|
free(atom_reply);
|
||||||
free(prop_reply);
|
free(prop_reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (asprintf(&content, "%.*s", xcb_get_property_value_length(prop_reply),
|
if (asprintf(&content, "%.*s", xcb_get_property_value_length(prop_reply),
|
||||||
(char*)xcb_get_property_value(prop_reply)) == -1) {
|
(char *)xcb_get_property_value(prop_reply)) == -1) {
|
||||||
free(atom_reply);
|
free(atom_reply);
|
||||||
free(prop_reply);
|
free(prop_reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -99,4 +99,3 @@ char *root_atom_contents(const char *atomname, xcb_connection_t *provided_conn,
|
|||||||
free(prop_reply);
|
free(prop_reply);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ char *convert_ucs2_to_utf8(xcb_char2b_t *text, size_t num_glyphs) {
|
|||||||
|
|
||||||
/* Do the conversion */
|
/* Do the conversion */
|
||||||
size_t input_len = num_glyphs * sizeof(xcb_char2b_t);
|
size_t input_len = num_glyphs * sizeof(xcb_char2b_t);
|
||||||
size_t rc = iconv(utf8_conversion_descriptor, (char**)&text,
|
size_t rc = iconv(utf8_conversion_descriptor, (char **)&text,
|
||||||
&input_len, &output, &output_size);
|
&input_len, &output, &output_size);
|
||||||
if (rc == (size_t)-1) {
|
if (rc == (size_t)-1) {
|
||||||
perror("Converting to UTF-8 failed");
|
perror("Converting to UTF-8 failed");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@ -83,8 +83,8 @@ xcb_char2b_t *convert_utf8_to_ucs2(char *input, size_t *real_strlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do the conversion */
|
/* Do the conversion */
|
||||||
size_t rc = iconv(ucs2_conversion_descriptor, (char**)&input,
|
size_t rc = iconv(ucs2_conversion_descriptor, (char **)&input,
|
||||||
&input_size, (char**)&output, &output_size);
|
&input_size, (char **)&output, &output_size);
|
||||||
if (rc == (size_t)-1) {
|
if (rc == (size_t)-1) {
|
||||||
perror("Converting to UCS-2 failed");
|
perror("Converting to UCS-2 failed");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
@ -23,7 +23,7 @@ void run_assignments(i3Window *window) {
|
|||||||
|
|
||||||
/* Check if any assignments match */
|
/* Check if any assignments match */
|
||||||
Assignment *current;
|
Assignment *current;
|
||||||
TAILQ_FOREACH(current, &assignments, assignments) {
|
TAILQ_FOREACH (current, &assignments, assignments) {
|
||||||
if (!match_matches_window(&(current->match), window))
|
if (!match_matches_window(&(current->match), window))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ void run_assignments(i3Window *window) {
|
|||||||
|
|
||||||
/* Store that we ran this assignment to not execute it again */
|
/* Store that we ran this assignment to not execute it again */
|
||||||
window->nr_assignments++;
|
window->nr_assignments++;
|
||||||
window->ran_assignments = srealloc(window->ran_assignments, sizeof(Assignment*) * window->nr_assignments);
|
window->ran_assignments = srealloc(window->ran_assignments, sizeof(Assignment *) * window->nr_assignments);
|
||||||
window->ran_assignments[window->nr_assignments-1] = current;
|
window->ran_assignments[window->nr_assignments - 1] = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If any of the commands required re-rendering, we will do that now. */
|
/* If any of the commands required re-rendering, we will do that now. */
|
||||||
@ -72,7 +72,7 @@ void run_assignments(i3Window *window) {
|
|||||||
Assignment *assignment_for(i3Window *window, int type) {
|
Assignment *assignment_for(i3Window *window, int type) {
|
||||||
Assignment *assignment;
|
Assignment *assignment;
|
||||||
|
|
||||||
TAILQ_FOREACH(assignment, &assignments, assignments) {
|
TAILQ_FOREACH (assignment, &assignments, assignments) {
|
||||||
if ((type != A_ANY && (assignment->type & type) == 0) ||
|
if ((type != A_ANY && (assignment->type & type) == 0) ||
|
||||||
!match_matches_window(&(assignment->match), window))
|
!match_matches_window(&(assignment->match), window))
|
||||||
continue;
|
continue;
|
||||||
|
@ -25,7 +25,7 @@ static struct Mode *mode_from_name(const char *name) {
|
|||||||
struct Mode *mode;
|
struct Mode *mode;
|
||||||
|
|
||||||
/* Try to find the mode in the list of modes and return it */
|
/* Try to find the mode in the list of modes and return it */
|
||||||
SLIST_FOREACH(mode, &modes, modes) {
|
SLIST_FOREACH (mode, &modes, modes) {
|
||||||
if (strcmp(mode->name, name) == 0)
|
if (strcmp(mode->name, name) == 0)
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
@ -47,14 +47,14 @@ static struct Mode *mode_from_name(const char *name) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
|
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
|
||||||
const char *release, const char *command, const char *modename) {
|
const char *release, const char *command, const char *modename) {
|
||||||
Binding *new_binding = scalloc(sizeof(Binding));
|
Binding *new_binding = scalloc(sizeof(Binding));
|
||||||
DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
|
DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
|
||||||
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
|
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
|
||||||
if (strcmp(bindtype, "bindsym") == 0) {
|
if (strcmp(bindtype, "bindsym") == 0) {
|
||||||
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
|
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
|
||||||
? B_MOUSE
|
? B_MOUSE
|
||||||
: B_KEYBOARD);
|
: B_KEYBOARD);
|
||||||
|
|
||||||
new_binding->symbol = sstrdup(input_code);
|
new_binding->symbol = sstrdup(input_code);
|
||||||
} else {
|
} else {
|
||||||
@ -81,12 +81,11 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
DLOG("Grabbing %d with modifiers %d (with mod_mask_lock %d)\n", keycode, bind->mods, bind->mods | XCB_MOD_MASK_LOCK);
|
DLOG("Grabbing %d with modifiers %d (with mod_mask_lock %d)\n", keycode, bind->mods, bind->mods | XCB_MOD_MASK_LOCK);
|
||||||
/* Grab the key in all combinations */
|
/* Grab the key in all combinations */
|
||||||
#define GRAB_KEY(modifier) \
|
#define GRAB_KEY(modifier) \
|
||||||
do { \
|
do { \
|
||||||
xcb_grab_key(conn, 0, root, modifier, keycode, \
|
xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \
|
||||||
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \
|
} while (0)
|
||||||
} while (0)
|
|
||||||
int mods = bind->mods;
|
int mods = bind->mods;
|
||||||
if ((bind->mods & BIND_MODE_SWITCH) != 0) {
|
if ((bind->mods & BIND_MODE_SWITCH) != 0) {
|
||||||
mods &= ~BIND_MODE_SWITCH;
|
mods &= ~BIND_MODE_SWITCH;
|
||||||
@ -99,17 +98,16 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint
|
|||||||
GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
|
GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab the bound keys (tell X to send us keypress events for those keycodes)
|
* Grab the bound keys (tell X to send us keypress events for those keycodes)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) {
|
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) {
|
||||||
Binding *bind;
|
Binding *bind;
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
if (bind->input_type != B_KEYBOARD ||
|
if (bind->input_type != B_KEYBOARD ||
|
||||||
(bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) == 0) ||
|
(bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) == 0) ||
|
||||||
(!bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) != 0))
|
(!bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) != 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* The easy case: the user specified a keycode directly. */
|
/* The easy case: the user specified a keycode directly. */
|
||||||
@ -135,7 +133,7 @@ static Binding *get_binding(uint16_t modifiers, bool is_release, uint16_t input_
|
|||||||
if (!is_release) {
|
if (!is_release) {
|
||||||
/* On a press event, we first reset all B_UPON_KEYRELEASE_IGNORE_MODS
|
/* On a press event, we first reset all B_UPON_KEYRELEASE_IGNORE_MODS
|
||||||
* bindings back to B_UPON_KEYRELEASE */
|
* bindings back to B_UPON_KEYRELEASE */
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
if (bind->input_type != input_type)
|
if (bind->input_type != input_type)
|
||||||
continue;
|
continue;
|
||||||
if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS)
|
if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS)
|
||||||
@ -143,7 +141,7 @@ static Binding *get_binding(uint16_t modifiers, bool is_release, uint16_t input_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
/* First compare the modifiers (unless this is a
|
/* First compare the modifiers (unless this is a
|
||||||
* B_UPON_KEYRELEASE_IGNORE_MODS binding and this is a KeyRelease
|
* B_UPON_KEYRELEASE_IGNORE_MODS binding and this is a KeyRelease
|
||||||
* event) */
|
* event) */
|
||||||
@ -192,13 +190,11 @@ static Binding *get_binding(uint16_t modifiers, bool is_release, uint16_t input_
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Binding *get_binding_from_xcb_event(xcb_generic_event_t *event) {
|
Binding *get_binding_from_xcb_event(xcb_generic_event_t *event) {
|
||||||
bool is_release = (event->response_type == XCB_KEY_RELEASE
|
bool is_release = (event->response_type == XCB_KEY_RELEASE || event->response_type == XCB_BUTTON_RELEASE);
|
||||||
|| event->response_type == XCB_BUTTON_RELEASE);
|
|
||||||
|
|
||||||
input_type_t input_type = ((event->response_type == XCB_BUTTON_RELEASE
|
input_type_t input_type = ((event->response_type == XCB_BUTTON_RELEASE || event->response_type == XCB_BUTTON_PRESS)
|
||||||
|| event->response_type == XCB_BUTTON_PRESS)
|
? B_MOUSE
|
||||||
? B_MOUSE
|
: B_KEYBOARD);
|
||||||
: B_KEYBOARD);
|
|
||||||
|
|
||||||
uint16_t event_state = ((xcb_key_press_event_t *)event)->state;
|
uint16_t event_state = ((xcb_key_press_event_t *)event)->state;
|
||||||
uint16_t event_detail = ((xcb_key_press_event_t *)event)->detail;
|
uint16_t event_detail = ((xcb_key_press_event_t *)event)->detail;
|
||||||
@ -252,7 +248,7 @@ void translate_keysyms(void) {
|
|||||||
min_keycode = xcb_get_setup(conn)->min_keycode;
|
min_keycode = xcb_get_setup(conn)->min_keycode;
|
||||||
max_keycode = xcb_get_setup(conn)->max_keycode;
|
max_keycode = xcb_get_setup(conn)->max_keycode;
|
||||||
|
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
if (bind->input_type == B_MOUSE) {
|
if (bind->input_type == B_MOUSE) {
|
||||||
int button = atoi(bind->symbol + (sizeof("button") - 1));
|
int button = atoi(bind->symbol + (sizeof("button") - 1));
|
||||||
bind->keycode = button;
|
bind->keycode = button;
|
||||||
@ -285,13 +281,13 @@ void translate_keysyms(void) {
|
|||||||
|
|
||||||
for (i = min_keycode; i && i <= max_keycode; i++) {
|
for (i = min_keycode; i && i <= max_keycode; i++) {
|
||||||
if ((xcb_key_symbols_get_keysym(keysyms, i, col) != keysym) &&
|
if ((xcb_key_symbols_get_keysym(keysyms, i, col) != keysym) &&
|
||||||
(xcb_key_symbols_get_keysym(keysyms, i, col+1) != keysym))
|
(xcb_key_symbols_get_keysym(keysyms, i, col + 1) != keysym))
|
||||||
continue;
|
continue;
|
||||||
bind->number_keycodes++;
|
bind->number_keycodes++;
|
||||||
bind->translated_to = srealloc(bind->translated_to,
|
bind->translated_to = srealloc(bind->translated_to,
|
||||||
(sizeof(xcb_keycode_t) *
|
(sizeof(xcb_keycode_t) *
|
||||||
bind->number_keycodes));
|
bind->number_keycodes));
|
||||||
bind->translated_to[bind->number_keycodes-1] = i;
|
bind->translated_to[bind->number_keycodes - 1] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG("Translated symbol \"%s\" to %d keycode\n", bind->symbol,
|
DLOG("Translated symbol \"%s\" to %d keycode\n", bind->symbol,
|
||||||
@ -308,7 +304,7 @@ void switch_mode(const char *new_mode) {
|
|||||||
|
|
||||||
DLOG("Switching to mode %s\n", new_mode);
|
DLOG("Switching to mode %s\n", new_mode);
|
||||||
|
|
||||||
SLIST_FOREACH(mode, &modes, modes) {
|
SLIST_FOREACH (mode, &modes, modes) {
|
||||||
if (strcasecmp(mode->name, new_mode) != 0)
|
if (strcasecmp(mode->name, new_mode) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -338,8 +334,8 @@ void switch_mode(const char *new_mode) {
|
|||||||
*/
|
*/
|
||||||
void check_for_duplicate_bindings(struct context *context) {
|
void check_for_duplicate_bindings(struct context *context) {
|
||||||
Binding *bind, *current;
|
Binding *bind, *current;
|
||||||
TAILQ_FOREACH(current, bindings, bindings) {
|
TAILQ_FOREACH (current, bindings, bindings) {
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
/* Abort when we reach the current keybinding, only check the
|
/* Abort when we reach the current keybinding, only check the
|
||||||
* bindings before */
|
* bindings before */
|
||||||
if (bind == current)
|
if (bind == current)
|
||||||
@ -413,8 +409,7 @@ CommandResult *run_binding(Binding *bind) {
|
|||||||
"-b",
|
"-b",
|
||||||
"show errors",
|
"show errors",
|
||||||
pageraction,
|
pageraction,
|
||||||
NULL
|
NULL};
|
||||||
};
|
|
||||||
start_nagbar(&command_error_nagbar_pid, argv);
|
start_nagbar(&command_error_nagbar_pid, argv);
|
||||||
free(pageraction);
|
free(pageraction);
|
||||||
}
|
}
|
||||||
|
12
src/click.c
12
src/click.c
@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
typedef enum { CLICK_BORDER = 0, CLICK_DECORATION = 1, CLICK_INSIDE = 2 } click_destination_t;
|
typedef enum { CLICK_BORDER = 0,
|
||||||
|
CLICK_DECORATION = 1,
|
||||||
|
CLICK_INSIDE = 2 } click_destination_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds the correct pair of first/second cons between the resize will take
|
* Finds the correct pair of first/second cons between the resize will take
|
||||||
@ -89,7 +91,7 @@ static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *eve
|
|||||||
to_bottom = con->rect.height - event->event_y;
|
to_bottom = con->rect.height - event->event_y;
|
||||||
|
|
||||||
DLOG("click was %d px to the right, %d px to the left, %d px to top, %d px to bottom\n",
|
DLOG("click was %d px to the right, %d px to the left, %d px to top, %d px to bottom\n",
|
||||||
to_right, to_left, to_top, to_bottom);
|
to_right, to_left, to_top, to_bottom);
|
||||||
|
|
||||||
if (to_right < to_left &&
|
if (to_right < to_left &&
|
||||||
to_right < to_top &&
|
to_right < to_top &&
|
||||||
@ -122,7 +124,7 @@ static bool tiling_resize(Con *con, xcb_button_press_event_t *event, const click
|
|||||||
/* check if this was a click on the window border (and on which one) */
|
/* check if this was a click on the window border (and on which one) */
|
||||||
Rect bsr = con_border_style_rect(con);
|
Rect bsr = con_border_style_rect(con);
|
||||||
DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x\n",
|
DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x\n",
|
||||||
event->event_x, event->event_y, con, event->event);
|
event->event_x, event->event_y, con, event->event);
|
||||||
DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width);
|
DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width);
|
||||||
if (dest == CLICK_DECORATION) {
|
if (dest == CLICK_DECORATION) {
|
||||||
/* The user clicked on a window decoration. We ignore the following case:
|
/* The user clicked on a window decoration. We ignore the following case:
|
||||||
@ -328,7 +330,7 @@ int handle_button_press(xcb_button_press_event_t *event) {
|
|||||||
* click coordinates and focus the output's active workspace. */
|
* click coordinates and focus the output's active workspace. */
|
||||||
if (event->event == root) {
|
if (event->event == root) {
|
||||||
Con *output, *ws;
|
Con *output, *ws;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
if (con_is_internal(output) ||
|
if (con_is_internal(output) ||
|
||||||
!rect_contains(output->rect, event->event_x, event->event_y))
|
!rect_contains(output->rect, event->event_x, event->event_y))
|
||||||
continue;
|
continue;
|
||||||
@ -356,7 +358,7 @@ int handle_button_press(xcb_button_press_event_t *event) {
|
|||||||
|
|
||||||
/* Check if the click was on the decoration of a child */
|
/* Check if the click was on the decoration of a child */
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
|
if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
225
src/commands.c
225
src/commands.c
@ -16,48 +16,50 @@
|
|||||||
#include "shmlog.h"
|
#include "shmlog.h"
|
||||||
|
|
||||||
// Macros to make the YAJL API a bit easier to use.
|
// Macros to make the YAJL API a bit easier to use.
|
||||||
#define y(x, ...) (cmd_output->json_gen != NULL ? yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__) : 0)
|
#define y(x, ...) (cmd_output->json_gen != NULL ? yajl_gen_##x(cmd_output->json_gen, ##__VA_ARGS__) : 0)
|
||||||
#define ystr(str) (cmd_output->json_gen != NULL ? yajl_gen_string(cmd_output->json_gen, (unsigned char*)str, strlen(str)) : 0)
|
#define ystr(str) (cmd_output->json_gen != NULL ? yajl_gen_string(cmd_output->json_gen, (unsigned char *)str, strlen(str)) : 0)
|
||||||
#define ysuccess(success) do { \
|
#define ysuccess(success) \
|
||||||
if (cmd_output->json_gen != NULL) { \
|
do { \
|
||||||
y(map_open); \
|
if (cmd_output->json_gen != NULL) { \
|
||||||
ystr("success"); \
|
y(map_open); \
|
||||||
y(bool, success); \
|
ystr("success"); \
|
||||||
y(map_close); \
|
y(bool, success); \
|
||||||
} \
|
y(map_close); \
|
||||||
} while (0)
|
} \
|
||||||
#define yerror(message) do { \
|
} while (0)
|
||||||
if (cmd_output->json_gen != NULL) { \
|
#define yerror(message) \
|
||||||
y(map_open); \
|
do { \
|
||||||
ystr("success"); \
|
if (cmd_output->json_gen != NULL) { \
|
||||||
y(bool, false); \
|
y(map_open); \
|
||||||
ystr("error"); \
|
ystr("success"); \
|
||||||
ystr(message); \
|
y(bool, false); \
|
||||||
y(map_close); \
|
ystr("error"); \
|
||||||
} \
|
ystr(message); \
|
||||||
} while (0)
|
y(map_close); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/** When the command did not include match criteria (!), we use the currently
|
/** When the command did not include match criteria (!), we use the currently
|
||||||
* focused container. Do not confuse this case with a command which included
|
* focused container. Do not confuse this case with a command which included
|
||||||
* criteria but which did not match any windows. This macro has to be called in
|
* criteria but which did not match any windows. This macro has to be called in
|
||||||
* every command.
|
* every command.
|
||||||
*/
|
*/
|
||||||
#define HANDLE_EMPTY_MATCH do { \
|
#define HANDLE_EMPTY_MATCH \
|
||||||
if (match_is_empty(current_match)) { \
|
do { \
|
||||||
owindow *ow = smalloc(sizeof(owindow)); \
|
if (match_is_empty(current_match)) { \
|
||||||
ow->con = focused; \
|
owindow *ow = smalloc(sizeof(owindow)); \
|
||||||
TAILQ_INIT(&owindows); \
|
ow->con = focused; \
|
||||||
TAILQ_INSERT_TAIL(&owindows, ow, owindows); \
|
TAILQ_INIT(&owindows); \
|
||||||
} \
|
TAILQ_INSERT_TAIL(&owindows, ow, owindows); \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if a is definitely greater than b (using the given epsilon)
|
* Returns true if a is definitely greater than b (using the given epsilon)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool definitelyGreaterThan(float a, float b, float epsilon) {
|
static bool definitelyGreaterThan(float a, float b, float epsilon) {
|
||||||
return (a - b) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
|
return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -76,7 +78,8 @@ static Output *get_output_from_string(Output *current_output, const char *output
|
|||||||
output = get_output_next_wrap(D_UP, current_output);
|
output = get_output_next_wrap(D_UP, current_output);
|
||||||
else if (strcasecmp(output_str, "down") == 0)
|
else if (strcasecmp(output_str, "down") == 0)
|
||||||
output = get_output_next_wrap(D_DOWN, current_output);
|
output = get_output_next_wrap(D_DOWN, current_output);
|
||||||
else output = get_output_by_name(output_str);
|
else
|
||||||
|
output = get_output_by_name(output_str);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -270,7 +273,7 @@ void cmd_criteria_init(I3_CMD) {
|
|||||||
}
|
}
|
||||||
TAILQ_INIT(&owindows);
|
TAILQ_INIT(&owindows);
|
||||||
/* copy all_cons */
|
/* copy all_cons */
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
ow = smalloc(sizeof(owindow));
|
ow = smalloc(sizeof(owindow));
|
||||||
ow->con = con;
|
ow->con = con;
|
||||||
TAILQ_INSERT_TAIL(&owindows, ow, owindows);
|
TAILQ_INSERT_TAIL(&owindows, ow, owindows);
|
||||||
@ -321,7 +324,7 @@ void cmd_criteria_match_windows(I3_CMD) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,7 +361,7 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) {
|
|||||||
(end && *end != '\0')) {
|
(end && *end != '\0')) {
|
||||||
ELOG("Could not parse con id \"%s\"\n", cvalue);
|
ELOG("Could not parse con id \"%s\"\n", cvalue);
|
||||||
} else {
|
} else {
|
||||||
current_match->con_id = (Con*)parsed;
|
current_match->con_id = (Con *)parsed;
|
||||||
DLOG("id as int = %p\n", current_match->con_id);
|
DLOG("id as int = %p\n", current_match->con_id);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -420,7 +423,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) {
|
|||||||
* when criteria wasn't specified and we don't have any window focused. */
|
* when criteria wasn't specified and we don't have any window focused. */
|
||||||
if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
|
if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
|
||||||
(match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
(match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
||||||
!con_has_children(focused))) {
|
!con_has_children(focused))) {
|
||||||
ysuccess(false);
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -445,7 +448,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_move_to_workspace(current->con, ws, true, false);
|
con_move_to_workspace(current->con, ws, true, false);
|
||||||
}
|
}
|
||||||
@ -472,7 +475,7 @@ void cmd_move_con_to_workspace_back_and_forth(I3_CMD) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_move_to_workspace(current->con, ws, true, false);
|
con_move_to_workspace(current->con, ws, true, false);
|
||||||
}
|
}
|
||||||
@ -502,9 +505,8 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
|||||||
ELOG("No windows match your criteria, cannot move.\n");
|
ELOG("No windows match your criteria, cannot move.\n");
|
||||||
ysuccess(false);
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
||||||
else if (match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
!con_has_children(focused)) {
|
||||||
!con_has_children(focused)) {
|
|
||||||
ysuccess(false);
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -517,7 +519,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_move_to_workspace(current->con, ws, true, false);
|
con_move_to_workspace(current->con, ws, true, false);
|
||||||
}
|
}
|
||||||
@ -539,7 +541,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
|||||||
* when criteria wasn't specified and we don't have any window focused. */
|
* when criteria wasn't specified and we don't have any window focused. */
|
||||||
if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
|
if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
|
||||||
(match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
(match_is_empty(current_match) && focused->type == CT_WORKSPACE &&
|
||||||
!con_has_children(focused))) {
|
!con_has_children(focused))) {
|
||||||
ysuccess(false);
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -560,9 +562,9 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(output),
|
GREP_FIRST(workspace, output_get_content(output),
|
||||||
child->num == parsed_num);
|
child->num == parsed_num);
|
||||||
|
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
workspace = workspace_get(which, NULL);
|
workspace = workspace_get(which, NULL);
|
||||||
@ -572,7 +574,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_move_to_workspace(current->con, workspace, true, false);
|
con_move_to_workspace(current->con, workspace, true, false);
|
||||||
}
|
}
|
||||||
@ -726,7 +728,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, char *way, char
|
|||||||
|
|
||||||
/* Ensure all the other children have a percentage set. */
|
/* Ensure all the other children have a percentage set. */
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
|
||||||
LOG("child->percent = %f (child %p)\n", child->percent, child);
|
LOG("child->percent = %f (child %p)\n", child->percent, child);
|
||||||
if (child->percent == 0.0)
|
if (child->percent == 0.0)
|
||||||
child->percent = percentage;
|
child->percent = percentage;
|
||||||
@ -738,7 +740,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, char *way, char
|
|||||||
LOG("subtract_percent = %f\n", subtract_percent);
|
LOG("subtract_percent = %f\n", subtract_percent);
|
||||||
/* Ensure that the new percentages are positive and greater than
|
/* Ensure that the new percentages are positive and greater than
|
||||||
* 0.05 to have a reasonable minimum size. */
|
* 0.05 to have a reasonable minimum size. */
|
||||||
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
|
||||||
if (child == current)
|
if (child == current)
|
||||||
continue;
|
continue;
|
||||||
if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) {
|
if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) {
|
||||||
@ -756,7 +758,7 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, char *way, char
|
|||||||
current->percent += ((double)ppt / 100.0);
|
current->percent += ((double)ppt / 100.0);
|
||||||
LOG("current->percent after = %f\n", current->percent);
|
LOG("current->percent after = %f\n", current->percent);
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(current->parent->nodes_head), nodes) {
|
||||||
if (child == current)
|
if (child == current)
|
||||||
continue;
|
continue;
|
||||||
child->percent -= subtract_percent;
|
child->percent -= subtract_percent;
|
||||||
@ -784,7 +786,7 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
|
|||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
owindow *current;
|
owindow *current;
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
/* Don't handle dock windows (issue #1201) */
|
/* Don't handle dock windows (issue #1201) */
|
||||||
if (current->con->window && current->con->window->dock) {
|
if (current->con->window && current->con->window->dock) {
|
||||||
DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
|
DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
|
||||||
@ -815,13 +817,13 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
|
|||||||
* Implementation of 'border normal|none|1pixel|toggle|pixel'.
|
* Implementation of 'border normal|none|1pixel|toggle|pixel'.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_border(I3_CMD, char *border_style_str, char *border_width ) {
|
void cmd_border(I3_CMD, char *border_style_str, char *border_width) {
|
||||||
DLOG("border style should be changed to %s with border width %s\n", border_style_str, border_width);
|
DLOG("border style should be changed to %s with border width %s\n", border_style_str, border_width);
|
||||||
owindow *current;
|
owindow *current;
|
||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
int border_style = current->con->border_style;
|
int border_style = current->con->border_style;
|
||||||
char *end;
|
char *end;
|
||||||
@ -845,7 +847,7 @@ void cmd_border(I3_CMD, char *border_style_str, char *border_width ) {
|
|||||||
border_style = BS_NORMAL;
|
border_style = BS_NORMAL;
|
||||||
else if (strcmp(border_style_str, "pixel") == 0)
|
else if (strcmp(border_style_str, "pixel") == 0)
|
||||||
border_style = BS_PIXEL;
|
border_style = BS_PIXEL;
|
||||||
else if (strcmp(border_style_str, "1pixel") == 0){
|
else if (strcmp(border_style_str, "1pixel") == 0) {
|
||||||
border_style = BS_PIXEL;
|
border_style = BS_PIXEL;
|
||||||
tmp_border_width = 1;
|
tmp_border_width = 1;
|
||||||
} else if (strcmp(border_style_str, "none") == 0)
|
} else if (strcmp(border_style_str, "none") == 0)
|
||||||
@ -965,9 +967,9 @@ void cmd_workspace_number(I3_CMD, char *which) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(output),
|
GREP_FIRST(workspace, output_get_content(output),
|
||||||
child->num == parsed_num);
|
child->num == parsed_num);
|
||||||
|
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
LOG("There is no workspace with number %ld, creating a new one.\n", parsed_num);
|
LOG("There is no workspace with number %ld, creating a new one.\n", parsed_num);
|
||||||
@ -1010,7 +1012,7 @@ void cmd_workspace_name(I3_CMD, char *name) {
|
|||||||
|
|
||||||
DLOG("should switch to workspace %s\n", name);
|
DLOG("should switch to workspace %s\n", name);
|
||||||
if (maybe_back_and_forth(cmd_output, name))
|
if (maybe_back_and_forth(cmd_output, name))
|
||||||
return;
|
return;
|
||||||
workspace_show_by_name(name);
|
workspace_show_by_name(name);
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
@ -1026,7 +1028,7 @@ void cmd_mark(I3_CMD, char *mark) {
|
|||||||
DLOG("Clearing all windows which have that mark first\n");
|
DLOG("Clearing all windows which have that mark first\n");
|
||||||
|
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
if (con->mark && strcmp(con->mark, mark) == 0)
|
if (con->mark && strcmp(con->mark, mark) == 0)
|
||||||
FREE(con->mark);
|
FREE(con->mark);
|
||||||
}
|
}
|
||||||
@ -1036,7 +1038,7 @@ void cmd_mark(I3_CMD, char *mark) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
current->con->mark = sstrdup(mark);
|
current->con->mark = sstrdup(mark);
|
||||||
}
|
}
|
||||||
@ -1051,19 +1053,19 @@ void cmd_mark(I3_CMD, char *mark) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_unmark(I3_CMD, char *mark) {
|
void cmd_unmark(I3_CMD, char *mark) {
|
||||||
if (mark == NULL) {
|
if (mark == NULL) {
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
FREE(con->mark);
|
FREE(con->mark);
|
||||||
}
|
}
|
||||||
DLOG("removed all window marks");
|
DLOG("removed all window marks");
|
||||||
} else {
|
} else {
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
if (con->mark && strcmp(con->mark, mark) == 0)
|
if (con->mark && strcmp(con->mark, mark) == 0)
|
||||||
FREE(con->mark);
|
FREE(con->mark);
|
||||||
}
|
}
|
||||||
DLOG("removed window mark %s\n", mark);
|
DLOG("removed window mark %s\n", mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
@ -1099,7 +1101,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
|
|||||||
Output *output;
|
Output *output;
|
||||||
|
|
||||||
// TODO: fix the handling of criteria
|
// TODO: fix the handling of criteria
|
||||||
TAILQ_FOREACH(current, &owindows, owindows)
|
TAILQ_FOREACH (current, &owindows, owindows)
|
||||||
current_output = get_output_of_con(current->con);
|
current_output = get_output_of_con(current->con);
|
||||||
|
|
||||||
assert(current_output != NULL);
|
assert(current_output != NULL);
|
||||||
@ -1130,7 +1132,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_move_to_workspace(current->con, ws, true, false);
|
con_move_to_workspace(current->con, ws, true, false);
|
||||||
}
|
}
|
||||||
@ -1151,7 +1153,7 @@ void cmd_floating(I3_CMD, char *floating_mode) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
if (strcmp(floating_mode, "toggle") == 0) {
|
if (strcmp(floating_mode, "toggle") == 0) {
|
||||||
DLOG("should toggle mode\n");
|
DLOG("should toggle mode\n");
|
||||||
@ -1181,7 +1183,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
|||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
owindow *current;
|
owindow *current;
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
Output *current_output = get_output_of_con(current->con);
|
Output *current_output = get_output_of_con(current->con);
|
||||||
if (!current_output) {
|
if (!current_output) {
|
||||||
ELOG("Cannot get current output. This is a bug in i3.\n");
|
ELOG("Cannot get current output. This is a bug in i3.\n");
|
||||||
@ -1211,13 +1213,13 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
|||||||
/* check if we can find a workspace assigned to this output */
|
/* check if we can find a workspace assigned to this output */
|
||||||
bool used_assignment = false;
|
bool used_assignment = false;
|
||||||
struct Workspace_Assignment *assignment;
|
struct Workspace_Assignment *assignment;
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcmp(assignment->output, current_output->name) != 0)
|
if (strcmp(assignment->output, current_output->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check if this workspace is already attached to the tree */
|
/* check if this workspace is already attached to the tree */
|
||||||
Con *workspace = NULL, *out;
|
Con *workspace = NULL, *out;
|
||||||
TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (out, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(out),
|
GREP_FIRST(workspace, output_get_content(out),
|
||||||
!strcasecmp(child->name, assignment->name));
|
!strcasecmp(child->name, assignment->name));
|
||||||
if (workspace != NULL)
|
if (workspace != NULL)
|
||||||
@ -1254,7 +1256,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
|||||||
|
|
||||||
/* fix the coordinates of the floating containers */
|
/* fix the coordinates of the floating containers */
|
||||||
Con *floating_con;
|
Con *floating_con;
|
||||||
TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
|
TAILQ_FOREACH (floating_con, &(ws->floating_head), floating_windows)
|
||||||
floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
|
floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"move\"}");
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"move\"}");
|
||||||
@ -1268,7 +1270,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
|||||||
* focus order/number of other workspaces on the output.
|
* focus order/number of other workspaces on the output.
|
||||||
* Instead, we loop through the available workspaces and only work with
|
* Instead, we loop through the available workspaces and only work with
|
||||||
* previously_visible_ws if we still find it. */
|
* previously_visible_ws if we still find it. */
|
||||||
TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
|
TAILQ_FOREACH (ws, &(content->nodes_head), nodes) {
|
||||||
if (ws != previously_visible_ws)
|
if (ws != previously_visible_ws)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1296,7 +1298,7 @@ void cmd_split(I3_CMD, char *direction) {
|
|||||||
if (match_is_empty(current_match))
|
if (match_is_empty(current_match))
|
||||||
tree_split(focused, (direction[0] == 'v' ? VERT : HORIZ));
|
tree_split(focused, (direction[0] == 'v' ? VERT : HORIZ));
|
||||||
else {
|
else {
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
|
tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
|
||||||
}
|
}
|
||||||
@ -1333,7 +1335,7 @@ void cmd_kill(I3_CMD, char *kill_mode_str) {
|
|||||||
if (match_is_empty(current_match))
|
if (match_is_empty(current_match))
|
||||||
tree_close_con(kill_mode);
|
tree_close_con(kill_mode);
|
||||||
else {
|
else {
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
tree_close(current->con, kill_mode, false, false);
|
tree_close(current->con, kill_mode, false, false);
|
||||||
}
|
}
|
||||||
@ -1398,9 +1400,10 @@ void cmd_focus_window_mode(I3_CMD, char *window_mode) {
|
|||||||
current = TAILQ_FIRST(&(ws->focus_head));
|
current = TAILQ_FIRST(&(ws->focus_head));
|
||||||
if (current != NULL && current->type == CT_FLOATING_CON)
|
if (current != NULL && current->type == CT_FLOATING_CON)
|
||||||
window_mode = "tiling";
|
window_mode = "tiling";
|
||||||
else window_mode = "floating";
|
else
|
||||||
|
window_mode = "floating";
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(current, &(ws->focus_head), focused) {
|
TAILQ_FOREACH (current, &(ws->focus_head), focused) {
|
||||||
if ((strcmp(window_mode, "floating") == 0 && current->type != CT_FLOATING_CON) ||
|
if ((strcmp(window_mode, "floating") == 0 && current->type != CT_FLOATING_CON) ||
|
||||||
(strcmp(window_mode, "tiling") == 0 && current->type == CT_FLOATING_CON))
|
(strcmp(window_mode, "tiling") == 0 && current->type == CT_FLOATING_CON))
|
||||||
continue;
|
continue;
|
||||||
@ -1435,7 +1438,8 @@ void cmd_focus_level(I3_CMD, char *level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Focusing a child should always be allowed. */
|
/* Focusing a child should always be allowed. */
|
||||||
else success = level_down();
|
else
|
||||||
|
success = level_down();
|
||||||
|
|
||||||
cmd_output->needs_tree_render = success;
|
cmd_output->needs_tree_render = success;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
@ -1461,7 +1465,7 @@ void cmd_focus(I3_CMD) {
|
|||||||
Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
|
Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
owindow *current;
|
owindow *current;
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
Con *ws = con_get_workspace(current->con);
|
Con *ws = con_get_workspace(current->con);
|
||||||
/* If no workspace could be found, this was a dock window.
|
/* If no workspace could be found, this was a dock window.
|
||||||
* Just skip it, you cannot focus dock windows. */
|
* Just skip it, you cannot focus dock windows. */
|
||||||
@ -1510,7 +1514,8 @@ void cmd_focus(I3_CMD) {
|
|||||||
|
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
LOG("WARNING: Your criteria for the focus command matches %d containers, "
|
LOG("WARNING: Your criteria for the focus command matches %d containers, "
|
||||||
"while only exactly one container can be focused at a time.\n", count);
|
"while only exactly one container can be focused at a time.\n",
|
||||||
|
count);
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
@ -1529,7 +1534,7 @@ void cmd_fullscreen(I3_CMD, char *fullscreen_mode) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_toggle_fullscreen(current->con, (strcmp(fullscreen_mode, "global") == 0 ? CF_GLOBAL : CF_OUTPUT));
|
con_toggle_fullscreen(current->con, (strcmp(fullscreen_mode, "global") == 0 ? CF_GLOBAL : CF_OUTPUT));
|
||||||
}
|
}
|
||||||
@ -1563,10 +1568,7 @@ void cmd_move_direction(I3_CMD, char *direction, char *move_px) {
|
|||||||
}
|
}
|
||||||
floating_reposition(focused->parent, newrect);
|
floating_reposition(focused->parent, newrect);
|
||||||
} else {
|
} else {
|
||||||
tree_move((strcmp(direction, "right") == 0 ? D_RIGHT :
|
tree_move((strcmp(direction, "right") == 0 ? D_RIGHT : (strcmp(direction, "left") == 0 ? D_LEFT : (strcmp(direction, "up") == 0 ? D_UP : D_DOWN))));
|
||||||
(strcmp(direction, "left") == 0 ? D_LEFT :
|
|
||||||
(strcmp(direction, "up") == 0 ? D_UP :
|
|
||||||
D_DOWN))));
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1605,7 +1607,7 @@ void cmd_layout(I3_CMD, char *layout_str) {
|
|||||||
if (match_is_empty(current_match))
|
if (match_is_empty(current_match))
|
||||||
con_set_layout(focused, layout);
|
con_set_layout(focused, layout);
|
||||||
else {
|
else {
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_set_layout(current->con, layout);
|
con_set_layout(current->con, layout);
|
||||||
}
|
}
|
||||||
@ -1632,7 +1634,7 @@ void cmd_layout_toggle(I3_CMD, char *toggle_mode) {
|
|||||||
if (match_is_empty(current_match))
|
if (match_is_empty(current_match))
|
||||||
con_toggle_layout(focused, toggle_mode);
|
con_toggle_layout(focused, toggle_mode);
|
||||||
else {
|
else {
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_toggle_layout(current->con, toggle_mode);
|
con_toggle_layout(current->con, toggle_mode);
|
||||||
}
|
}
|
||||||
@ -1731,7 +1733,7 @@ void cmd_focus_output(I3_CMD, char *name) {
|
|||||||
Output *current_output = NULL;
|
Output *current_output = NULL;
|
||||||
Output *output;
|
Output *output;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows)
|
TAILQ_FOREACH (current, &owindows, owindows)
|
||||||
current_output = get_output_of_con(current->con);
|
current_output = get_output_of_con(current->con);
|
||||||
assert(current_output != NULL);
|
assert(current_output != NULL);
|
||||||
|
|
||||||
@ -1763,7 +1765,6 @@ void cmd_focus_output(I3_CMD, char *name) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
|
void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
|
||||||
|
|
||||||
int x = atoi(cx);
|
int x = atoi(cx);
|
||||||
int y = atoi(cy);
|
int y = atoi(cy);
|
||||||
|
|
||||||
@ -1801,7 +1802,6 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_move_window_to_center(I3_CMD, char *method) {
|
void cmd_move_window_to_center(I3_CMD, char *method) {
|
||||||
|
|
||||||
if (!con_is_floating(focused)) {
|
if (!con_is_floating(focused)) {
|
||||||
ELOG("Cannot change position. The window/container is not floating\n");
|
ELOG("Cannot change position. The window/container is not floating\n");
|
||||||
yerror("Cannot change position. The window/container is not floating.");
|
yerror("Cannot change position. The window/container is not floating.");
|
||||||
@ -1812,8 +1812,8 @@ void cmd_move_window_to_center(I3_CMD, char *method) {
|
|||||||
Rect *rect = &focused->parent->rect;
|
Rect *rect = &focused->parent->rect;
|
||||||
|
|
||||||
DLOG("moving to absolute center\n");
|
DLOG("moving to absolute center\n");
|
||||||
rect->x = croot->rect.width/2 - rect->width/2;
|
rect->x = croot->rect.width / 2 - rect->width / 2;
|
||||||
rect->y = croot->rect.height/2 - rect->height/2;
|
rect->y = croot->rect.height / 2 - rect->height / 2;
|
||||||
|
|
||||||
floating_maybe_reassign_ws(focused->parent);
|
floating_maybe_reassign_ws(focused->parent);
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
@ -1824,8 +1824,8 @@ void cmd_move_window_to_center(I3_CMD, char *method) {
|
|||||||
Rect newrect = focused->parent->rect;
|
Rect newrect = focused->parent->rect;
|
||||||
|
|
||||||
DLOG("moving to center\n");
|
DLOG("moving to center\n");
|
||||||
newrect.x = wsrect->width/2 - newrect.width/2;
|
newrect.x = wsrect->width / 2 - newrect.width / 2;
|
||||||
newrect.y = wsrect->height/2 - newrect.height/2;
|
newrect.y = wsrect->height / 2 - newrect.height / 2;
|
||||||
|
|
||||||
floating_reposition(focused->parent, newrect);
|
floating_reposition(focused->parent, newrect);
|
||||||
}
|
}
|
||||||
@ -1844,7 +1844,7 @@ void cmd_move_scratchpad(I3_CMD) {
|
|||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
scratchpad_move(current->con);
|
scratchpad_move(current->con);
|
||||||
}
|
}
|
||||||
@ -1865,7 +1865,7 @@ void cmd_scratchpad_show(I3_CMD) {
|
|||||||
if (match_is_empty(current_match)) {
|
if (match_is_empty(current_match)) {
|
||||||
scratchpad_show(NULL);
|
scratchpad_show(NULL);
|
||||||
} else {
|
} else {
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH (current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
scratchpad_show(current->con);
|
scratchpad_show(current->con);
|
||||||
}
|
}
|
||||||
@ -1894,9 +1894,9 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
|||||||
|
|
||||||
Con *output, *workspace = NULL;
|
Con *output, *workspace = NULL;
|
||||||
if (old_name) {
|
if (old_name) {
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(output),
|
GREP_FIRST(workspace, output_get_content(output),
|
||||||
!strcasecmp(child->name, old_name));
|
!strcasecmp(child->name, old_name));
|
||||||
} else {
|
} else {
|
||||||
workspace = con_get_workspace(focused);
|
workspace = con_get_workspace(focused);
|
||||||
}
|
}
|
||||||
@ -1910,9 +1910,9 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Con *check_dest = NULL;
|
Con *check_dest = NULL;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(check_dest, output_get_content(output),
|
GREP_FIRST(check_dest, output_get_content(output),
|
||||||
!strcasecmp(child->name, new_name));
|
!strcasecmp(child->name, new_name));
|
||||||
|
|
||||||
if (check_dest != NULL) {
|
if (check_dest != NULL) {
|
||||||
// TODO: we should include the new workspace name here and use yajl for
|
// TODO: we should include the new workspace name here and use yajl for
|
||||||
@ -1932,7 +1932,8 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
|||||||
parsed_num < 0 ||
|
parsed_num < 0 ||
|
||||||
endptr == new_name)
|
endptr == new_name)
|
||||||
workspace->num = -1;
|
workspace->num = -1;
|
||||||
else workspace->num = parsed_num;
|
else
|
||||||
|
workspace->num = parsed_num;
|
||||||
LOG("num = %d\n", workspace->num);
|
LOG("num = %d\n", workspace->num);
|
||||||
|
|
||||||
/* By re-attaching, the sort order will be correct afterwards. */
|
/* By re-attaching, the sort order will be correct afterwards. */
|
||||||
@ -1971,7 +1972,7 @@ bool cmd_bar_mode(char *bar_mode, char *bar_id) {
|
|||||||
|
|
||||||
bool changed_sth = false;
|
bool changed_sth = false;
|
||||||
Barconfig *current = NULL;
|
Barconfig *current = NULL;
|
||||||
TAILQ_FOREACH(current, &barconfigs, configs) {
|
TAILQ_FOREACH (current, &barconfigs, configs) {
|
||||||
if (bar_id && strcmp(current->id, bar_id) != 0)
|
if (bar_id && strcmp(current->id, bar_id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1983,7 +1984,7 @@ bool cmd_bar_mode(char *bar_mode, char *bar_id) {
|
|||||||
changed_sth = true;
|
changed_sth = true;
|
||||||
|
|
||||||
if (bar_id)
|
if (bar_id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bar_id && !changed_sth) {
|
if (bar_id && !changed_sth) {
|
||||||
@ -2014,7 +2015,7 @@ bool cmd_bar_hidden_state(char *bar_hidden_state, char *bar_id) {
|
|||||||
|
|
||||||
bool changed_sth = false;
|
bool changed_sth = false;
|
||||||
Barconfig *current = NULL;
|
Barconfig *current = NULL;
|
||||||
TAILQ_FOREACH(current, &barconfigs, configs) {
|
TAILQ_FOREACH (current, &barconfigs, configs) {
|
||||||
if (bar_id && strcmp(current->id, bar_id) != 0)
|
if (bar_id && strcmp(current->id, bar_id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2026,7 +2027,7 @@ bool cmd_bar_hidden_state(char *bar_hidden_state, char *bar_id) {
|
|||||||
changed_sth = true;
|
changed_sth = true;
|
||||||
|
|
||||||
if (bar_id)
|
if (bar_id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bar_id && !changed_sth) {
|
if (bar_id && !changed_sth) {
|
||||||
@ -2064,7 +2065,7 @@ void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_shmlog(I3_CMD, char *argument) {
|
void cmd_shmlog(I3_CMD, char *argument) {
|
||||||
if (!strcmp(argument,"toggle"))
|
if (!strcmp(argument, "toggle"))
|
||||||
/* Toggle shm log, if size is not 0. If it is 0, set it to default. */
|
/* Toggle shm log, if size is not 0. If it is 0, set it to default. */
|
||||||
shmlog_size = shmlog_size ? -shmlog_size : default_shmlog_size;
|
shmlog_size = shmlog_size ? -shmlog_size : default_shmlog_size;
|
||||||
else if (!strcmp(argument, "on"))
|
else if (!strcmp(argument, "on"))
|
||||||
@ -2096,7 +2097,7 @@ void cmd_shmlog(I3_CMD, char *argument) {
|
|||||||
*/
|
*/
|
||||||
void cmd_debuglog(I3_CMD, char *argument) {
|
void cmd_debuglog(I3_CMD, char *argument) {
|
||||||
bool logging = get_debug_logging();
|
bool logging = get_debug_logging();
|
||||||
if (!strcmp(argument,"toggle")) {
|
if (!strcmp(argument, "toggle")) {
|
||||||
LOG("%s debug logging\n", logging ? "Disabling" : "Enabling");
|
LOG("%s debug logging\n", logging ? "Disabling" : "Enabling");
|
||||||
set_debug_logging(!logging);
|
set_debug_logging(!logging);
|
||||||
} else if (!strcmp(argument, "on") && !logging) {
|
} else if (!strcmp(argument, "on") && !logging) {
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
// Macros to make the YAJL API a bit easier to use.
|
// Macros to make the YAJL API a bit easier to use.
|
||||||
#define y(x, ...) (command_output.json_gen != NULL ? yajl_gen_ ## x (command_output.json_gen, ##__VA_ARGS__) : 0)
|
#define y(x, ...) (command_output.json_gen != NULL ? yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__) : 0)
|
||||||
#define ystr(str) (command_output.json_gen != NULL ? yajl_gen_string(command_output.json_gen, (unsigned char*)str, strlen(str)) : 0)
|
#define ystr(str) (command_output.json_gen != NULL ? yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str)) : 0)
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* The data structures used for parsing. Essentially the current state and a
|
* The data structures used for parsing. Essentially the current state and a
|
||||||
@ -184,7 +184,6 @@ static struct CommandResultIR command_output;
|
|||||||
|
|
||||||
#include "GENERATED_command_call.h"
|
#include "GENERATED_command_call.h"
|
||||||
|
|
||||||
|
|
||||||
static void next_state(const cmdp_token *token) {
|
static void next_state(const cmdp_token *token) {
|
||||||
if (token->next_state == __CALL) {
|
if (token->next_state == __CALL) {
|
||||||
subcommand_output.json_gen = command_output.json_gen;
|
subcommand_output.json_gen = command_output.json_gen;
|
||||||
@ -229,7 +228,7 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
|
|||||||
const cmdp_token *token;
|
const cmdp_token *token;
|
||||||
bool token_handled;
|
bool token_handled;
|
||||||
|
|
||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
#ifndef TEST_PARSER
|
#ifndef TEST_PARSER
|
||||||
cmd_criteria_init(¤t_match, &subcommand_output);
|
cmd_criteria_init(¤t_match, &subcommand_output);
|
||||||
#endif
|
#endif
|
||||||
@ -239,7 +238,8 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
|
|||||||
while ((size_t)(walk - input) <= len) {
|
while ((size_t)(walk - input) <= len) {
|
||||||
/* skip whitespace and newlines before every token */
|
/* skip whitespace and newlines before every token */
|
||||||
while ((*walk == ' ' || *walk == '\t' ||
|
while ((*walk == ' ' || *walk == '\t' ||
|
||||||
*walk == '\r' || *walk == '\n') && *walk != '\0')
|
*walk == '\r' || *walk == '\n') &&
|
||||||
|
*walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
|
|
||||||
cmdp_token_ptr *ptr = &(tokens[state]);
|
cmdp_token_ptr *ptr = &(tokens[state]);
|
||||||
@ -267,7 +267,7 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
|
|||||||
if (*walk == '"') {
|
if (*walk == '"') {
|
||||||
beginning++;
|
beginning++;
|
||||||
walk++;
|
walk++;
|
||||||
while (*walk != '\0' && (*walk != '"' || *(walk-1) == '\\'))
|
while (*walk != '\0' && (*walk != '"' || *(walk - 1) == '\\'))
|
||||||
walk++;
|
walk++;
|
||||||
} else {
|
} else {
|
||||||
if (token->name[0] == 's') {
|
if (token->name[0] == 's') {
|
||||||
@ -285,22 +285,22 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
|
|||||||
* semicolon (;). */
|
* semicolon (;). */
|
||||||
while (*walk != ' ' && *walk != '\t' &&
|
while (*walk != ' ' && *walk != '\t' &&
|
||||||
*walk != ']' && *walk != ',' &&
|
*walk != ']' && *walk != ',' &&
|
||||||
*walk != ';' && *walk != '\r' &&
|
*walk != ';' && *walk != '\r' &&
|
||||||
*walk != '\n' && *walk != '\0')
|
*walk != '\n' && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (walk != beginning) {
|
if (walk != beginning) {
|
||||||
char *str = scalloc(walk-beginning + 1);
|
char *str = scalloc(walk - beginning + 1);
|
||||||
/* We copy manually to handle escaping of characters. */
|
/* We copy manually to handle escaping of characters. */
|
||||||
int inpos, outpos;
|
int inpos, outpos;
|
||||||
for (inpos = 0, outpos = 0;
|
for (inpos = 0, outpos = 0;
|
||||||
inpos < (walk-beginning);
|
inpos < (walk - beginning);
|
||||||
inpos++, outpos++) {
|
inpos++, outpos++) {
|
||||||
/* We only handle escaped double quotes to not break
|
/* We only handle escaped double quotes to not break
|
||||||
* backwards compatibility with people using \w in
|
* backwards compatibility with people using \w in
|
||||||
* regular expressions etc. */
|
* regular expressions etc. */
|
||||||
if (beginning[inpos] == '\\' && beginning[inpos+1] == '"')
|
if (beginning[inpos] == '\\' && beginning[inpos + 1] == '"')
|
||||||
inpos++;
|
inpos++;
|
||||||
str[outpos] = beginning[inpos];
|
str[outpos] = beginning[inpos];
|
||||||
}
|
}
|
||||||
@ -320,19 +320,19 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
|
|||||||
if (*walk == '\0' || *walk == ',' || *walk == ';') {
|
if (*walk == '\0' || *walk == ',' || *walk == ';') {
|
||||||
next_state(token);
|
next_state(token);
|
||||||
token_handled = true;
|
token_handled = true;
|
||||||
/* To make sure we start with an appropriate matching
|
/* To make sure we start with an appropriate matching
|
||||||
* datastructure for commands which do *not* specify any
|
* datastructure for commands which do *not* specify any
|
||||||
* criteria, we re-initialize the criteria system after
|
* criteria, we re-initialize the criteria system after
|
||||||
* every command. */
|
* every command. */
|
||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
#ifndef TEST_PARSER
|
#ifndef TEST_PARSER
|
||||||
if (*walk == '\0' || *walk == ';')
|
if (*walk == '\0' || *walk == ';')
|
||||||
cmd_criteria_init(¤t_match, &subcommand_output);
|
cmd_criteria_init(¤t_match, &subcommand_output);
|
||||||
#endif
|
#endif
|
||||||
walk++;
|
walk++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!token_handled) {
|
if (!token_handled) {
|
||||||
|
106
src/con.c
106
src/con.c
@ -23,8 +23,7 @@ char *colors[] = {
|
|||||||
"#aa0000",
|
"#aa0000",
|
||||||
"#00aa00",
|
"#00aa00",
|
||||||
"#0000aa",
|
"#0000aa",
|
||||||
"#aa00aa"
|
"#aa00aa"};
|
||||||
};
|
|
||||||
|
|
||||||
static void con_on_remove_child(Con *con);
|
static void con_on_remove_child(Con *con);
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ Con *con_new_skeleton(Con *parent, i3Window *window) {
|
|||||||
new->name = strdup(colors[cnt]);
|
new->name = strdup(colors[cnt]);
|
||||||
//uint32_t cp = get_colorpixel(colors[cnt]);
|
//uint32_t cp = get_colorpixel(colors[cnt]);
|
||||||
cnt++;
|
cnt++;
|
||||||
if ((cnt % (sizeof(colors) / sizeof(char*))) == 0)
|
if ((cnt % (sizeof(colors) / sizeof(char *))) == 0)
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
|
||||||
TAILQ_INIT(&(new->floating_head));
|
TAILQ_INIT(&(new->floating_head));
|
||||||
@ -130,7 +129,8 @@ void con_attach(Con *con, Con *parent, bool ignore_focus) {
|
|||||||
/* we need to insert con after current, if current is not NULL */
|
/* we need to insert con after current, if current is not NULL */
|
||||||
if (current)
|
if (current)
|
||||||
TAILQ_INSERT_BEFORE(current, con, nodes);
|
TAILQ_INSERT_BEFORE(current, con, nodes);
|
||||||
else TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
else
|
||||||
|
TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto add_to_focus_head;
|
goto add_to_focus_head;
|
||||||
@ -142,7 +142,7 @@ void con_attach(Con *con, Con *parent, bool ignore_focus) {
|
|||||||
} else {
|
} else {
|
||||||
if (!ignore_focus) {
|
if (!ignore_focus) {
|
||||||
/* Get the first tiling container in focus stack */
|
/* Get the first tiling container in focus stack */
|
||||||
TAILQ_FOREACH(loop, &(parent->focus_head), focused) {
|
TAILQ_FOREACH (loop, &(parent->focus_head), focused) {
|
||||||
if (loop->type == CT_FLOATING_CON)
|
if (loop->type == CT_FLOATING_CON)
|
||||||
continue;
|
continue;
|
||||||
current = loop;
|
current = loop;
|
||||||
@ -178,7 +178,8 @@ void con_attach(Con *con, Con *parent, bool ignore_focus) {
|
|||||||
DLOG("Inserting con = %p after last focused tiling con %p\n",
|
DLOG("Inserting con = %p after last focused tiling con %p\n",
|
||||||
con, current);
|
con, current);
|
||||||
TAILQ_INSERT_AFTER(nodes_head, current, con, nodes);
|
TAILQ_INSERT_AFTER(nodes_head, current, con, nodes);
|
||||||
} else TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
} else
|
||||||
|
TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_focus_head:
|
add_to_focus_head:
|
||||||
@ -246,10 +247,7 @@ bool con_is_leaf(Con *con) {
|
|||||||
* excluding dock containers)
|
* excluding dock containers)
|
||||||
*/
|
*/
|
||||||
bool con_has_managed_window(Con *con) {
|
bool con_has_managed_window(Con *con) {
|
||||||
return (con != NULL
|
return (con != NULL && con->window != NULL && con->window->id != XCB_WINDOW_NONE && con_get_workspace(con) != NULL);
|
||||||
&& con->window != NULL
|
|
||||||
&& con->window->id != XCB_WINDOW_NONE
|
|
||||||
&& con_get_workspace(con) != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -390,13 +388,13 @@ Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode) {
|
|||||||
TAILQ_REMOVE(&bfs_head, entry, entries);
|
TAILQ_REMOVE(&bfs_head, entry, entries);
|
||||||
free(entry);
|
free(entry);
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(current->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(current->nodes_head), nodes) {
|
||||||
entry = smalloc(sizeof(struct bfs_entry));
|
entry = smalloc(sizeof(struct bfs_entry));
|
||||||
entry->con = child;
|
entry->con = child;
|
||||||
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
|
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(current->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(current->floating_head), floating_windows) {
|
||||||
entry = smalloc(sizeof(struct bfs_entry));
|
entry = smalloc(sizeof(struct bfs_entry));
|
||||||
entry->con = child;
|
entry->con = child;
|
||||||
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
|
TAILQ_INSERT_TAIL(&bfs_head, entry, entries);
|
||||||
@ -462,7 +460,7 @@ bool con_inside_focused(Con *con) {
|
|||||||
*/
|
*/
|
||||||
Con *con_by_window_id(xcb_window_t window) {
|
Con *con_by_window_id(xcb_window_t window) {
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons)
|
TAILQ_FOREACH (con, &all_cons, all_cons)
|
||||||
if (con->window != NULL && con->window->id == window)
|
if (con->window != NULL && con->window->id == window)
|
||||||
return con;
|
return con;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -475,7 +473,7 @@ Con *con_by_window_id(xcb_window_t window) {
|
|||||||
*/
|
*/
|
||||||
Con *con_by_frame_id(xcb_window_t frame) {
|
Con *con_by_frame_id(xcb_window_t frame) {
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons)
|
TAILQ_FOREACH (con, &all_cons, all_cons)
|
||||||
if (con->frame == frame)
|
if (con->frame == frame)
|
||||||
return con;
|
return con;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -492,8 +490,8 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
|
|||||||
//DLOG("searching con for window %p starting at con %p\n", window, con);
|
//DLOG("searching con for window %p starting at con %p\n", window, con);
|
||||||
//DLOG("class == %s\n", window->class_class);
|
//DLOG("class == %s\n", window->class_class);
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
TAILQ_FOREACH(match, &(child->swallow_head), matches) {
|
TAILQ_FOREACH (match, &(child->swallow_head), matches) {
|
||||||
if (!match_matches_window(match, window))
|
if (!match_matches_window(match, window))
|
||||||
continue;
|
continue;
|
||||||
if (store_match != NULL)
|
if (store_match != NULL)
|
||||||
@ -505,8 +503,8 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
|
||||||
TAILQ_FOREACH(match, &(child->swallow_head), matches) {
|
TAILQ_FOREACH (match, &(child->swallow_head), matches) {
|
||||||
if (!match_matches_window(match, window))
|
if (!match_matches_window(match, window))
|
||||||
continue;
|
continue;
|
||||||
if (store_match != NULL)
|
if (store_match != NULL)
|
||||||
@ -529,7 +527,7 @@ int con_num_children(Con *con) {
|
|||||||
Con *child;
|
Con *child;
|
||||||
int children = 0;
|
int children = 0;
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
children++;
|
children++;
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
@ -549,7 +547,7 @@ void con_fix_percent(Con *con) {
|
|||||||
// with a percentage set we have
|
// with a percentage set we have
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
int children_with_percent = 0;
|
int children_with_percent = 0;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (child->percent > 0.0) {
|
if (child->percent > 0.0) {
|
||||||
total += child->percent;
|
total += child->percent;
|
||||||
++children_with_percent;
|
++children_with_percent;
|
||||||
@ -559,11 +557,12 @@ void con_fix_percent(Con *con) {
|
|||||||
// if there were children without a percentage set, set to a value that
|
// if there were children without a percentage set, set to a value that
|
||||||
// will make those children proportional to all others
|
// will make those children proportional to all others
|
||||||
if (children_with_percent != children) {
|
if (children_with_percent != children) {
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (child->percent <= 0.0) {
|
if (child->percent <= 0.0) {
|
||||||
if (children_with_percent == 0)
|
if (children_with_percent == 0)
|
||||||
total += (child->percent = 1.0);
|
total += (child->percent = 1.0);
|
||||||
else total += (child->percent = total / children_with_percent);
|
else
|
||||||
|
total += (child->percent = total / children_with_percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,10 +570,10 @@ void con_fix_percent(Con *con) {
|
|||||||
// if we got a zero, just distribute the space equally, otherwise
|
// if we got a zero, just distribute the space equally, otherwise
|
||||||
// distribute according to the proportions we got
|
// distribute according to the proportions we got
|
||||||
if (total == 0.0) {
|
if (total == 0.0) {
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
child->percent = 1.0 / children;
|
child->percent = 1.0 / children;
|
||||||
} else if (total != 1.0) {
|
} else if (total != 1.0) {
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
child->percent /= total;
|
child->percent /= total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -733,7 +732,8 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
|||||||
* to the coordinate space of the correct output */
|
* to the coordinate space of the correct output */
|
||||||
if (fix_coordinates && con->type == CT_FLOATING_CON) {
|
if (fix_coordinates && con->type == CT_FLOATING_CON) {
|
||||||
floating_fix_coordinates(con, &(source_output->rect), &(dest_output->rect));
|
floating_fix_coordinates(con, &(source_output->rect), &(dest_output->rect));
|
||||||
} else DLOG("Not fixing coordinates, fix_coordinates flag = %d\n", fix_coordinates);
|
} else
|
||||||
|
DLOG("Not fixing coordinates, fix_coordinates flag = %d\n", fix_coordinates);
|
||||||
|
|
||||||
/* If moving to a visible workspace, call show so it can be considered
|
/* If moving to a visible workspace, call show so it can be considered
|
||||||
* focused. Must do before attaching because workspace_show checks to see
|
* focused. Must do before attaching because workspace_show checks to see
|
||||||
@ -797,7 +797,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
|||||||
/* Set focus only if con was on current workspace before moving.
|
/* Set focus only if con was on current workspace before moving.
|
||||||
* Otherwise we would give focus to some window on different workspace. */
|
* Otherwise we would give focus to some window on different workspace. */
|
||||||
if (source_ws == current_ws)
|
if (source_ws == current_ws)
|
||||||
con_focus(con_descend_focused(focus_next));
|
con_focus(con_descend_focused(focus_next));
|
||||||
|
|
||||||
/* If anything within the container is associated with a startup sequence,
|
/* If anything within the container is associated with a startup sequence,
|
||||||
* delete it so child windows won't be created on the old workspace. */
|
* delete it so child windows won't be created on the old workspace. */
|
||||||
@ -807,12 +807,12 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
|||||||
|
|
||||||
if (!con_is_leaf(con)) {
|
if (!con_is_leaf(con)) {
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (!child->window)
|
if (!child->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cookie = xcb_get_property(conn, false, child->window->id,
|
cookie = xcb_get_property(conn, false, child->window->id,
|
||||||
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
||||||
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
||||||
|
|
||||||
sequence = startup_sequence_get(child->window, startup_id_reply, true);
|
sequence = startup_sequence_get(child->window, startup_id_reply, true);
|
||||||
@ -823,7 +823,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
|||||||
|
|
||||||
if (con->window) {
|
if (con->window) {
|
||||||
cookie = xcb_get_property(conn, false, con->window->id,
|
cookie = xcb_get_property(conn, false, con->window->id,
|
||||||
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
||||||
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
||||||
|
|
||||||
sequence = startup_sequence_get(con->window, startup_id_reply, true);
|
sequence = startup_sequence_get(con->window, startup_id_reply, true);
|
||||||
@ -1003,7 +1003,7 @@ Con *con_descend_tiling_focused(Con *con) {
|
|||||||
return next;
|
return next;
|
||||||
do {
|
do {
|
||||||
before = next;
|
before = next;
|
||||||
TAILQ_FOREACH(child, &(next->focus_head), focused) {
|
TAILQ_FOREACH (child, &(next->focus_head), focused) {
|
||||||
if (child->type == CT_FLOATING_CON)
|
if (child->type == CT_FLOATING_CON)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1032,12 +1032,13 @@ Con *con_descend_direction(Con *con, direction_t direction) {
|
|||||||
* (D_RIGHT) or the last con (D_LEFT) */
|
* (D_RIGHT) or the last con (D_LEFT) */
|
||||||
if (direction == D_RIGHT)
|
if (direction == D_RIGHT)
|
||||||
most = TAILQ_FIRST(&(con->nodes_head));
|
most = TAILQ_FIRST(&(con->nodes_head));
|
||||||
else most = TAILQ_LAST(&(con->nodes_head), nodes_head);
|
else
|
||||||
|
most = TAILQ_LAST(&(con->nodes_head), nodes_head);
|
||||||
} else if (orientation == VERT) {
|
} else if (orientation == VERT) {
|
||||||
/* Wrong orientation. We use the last focused con. Within that con,
|
/* Wrong orientation. We use the last focused con. Within that con,
|
||||||
* we recurse to chose the left/right con or at least the last
|
* we recurse to chose the left/right con or at least the last
|
||||||
* focused one. */
|
* focused one. */
|
||||||
TAILQ_FOREACH(current, &(con->focus_head), focused) {
|
TAILQ_FOREACH (current, &(con->focus_head), focused) {
|
||||||
if (current->type != CT_FLOATING_CON) {
|
if (current->type != CT_FLOATING_CON) {
|
||||||
most = current;
|
most = current;
|
||||||
break;
|
break;
|
||||||
@ -1056,12 +1057,13 @@ Con *con_descend_direction(Con *con, direction_t direction) {
|
|||||||
* (D_DOWN) or the last con (D_UP) */
|
* (D_DOWN) or the last con (D_UP) */
|
||||||
if (direction == D_UP)
|
if (direction == D_UP)
|
||||||
most = TAILQ_LAST(&(con->nodes_head), nodes_head);
|
most = TAILQ_LAST(&(con->nodes_head), nodes_head);
|
||||||
else most = TAILQ_FIRST(&(con->nodes_head));
|
else
|
||||||
|
most = TAILQ_FIRST(&(con->nodes_head));
|
||||||
} else if (orientation == HORIZ) {
|
} else if (orientation == HORIZ) {
|
||||||
/* Wrong orientation. We use the last focused con. Within that con,
|
/* Wrong orientation. We use the last focused con. Within that con,
|
||||||
* we recurse to chose the top/bottom con or at least the last
|
* we recurse to chose the top/bottom con or at least the last
|
||||||
* focused one. */
|
* focused one. */
|
||||||
TAILQ_FOREACH(current, &(con->focus_head), focused) {
|
TAILQ_FOREACH (current, &(con->focus_head), focused) {
|
||||||
if (current->type != CT_FLOATING_CON) {
|
if (current->type != CT_FLOATING_CON) {
|
||||||
most = current;
|
most = current;
|
||||||
break;
|
break;
|
||||||
@ -1101,18 +1103,18 @@ Rect con_border_style_rect(Con *con) {
|
|||||||
/* Shortcut to avoid calling con_adjacent_borders() on dock containers. */
|
/* Shortcut to avoid calling con_adjacent_borders() on dock containers. */
|
||||||
int border_style = con_border_style(con);
|
int border_style = con_border_style(con);
|
||||||
if (border_style == BS_NONE)
|
if (border_style == BS_NONE)
|
||||||
return (Rect){ 0, 0, 0, 0 };
|
return (Rect) {0, 0, 0, 0};
|
||||||
borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
|
borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
|
||||||
if (border_style == BS_NORMAL) {
|
if (border_style == BS_NORMAL) {
|
||||||
result = (Rect){border_width, 0 , -(2 * border_width), -(border_width)};
|
result = (Rect) {border_width, 0, -(2 * border_width), -(border_width)};
|
||||||
} else {
|
} else {
|
||||||
result = (Rect){border_width, border_width, -(2 * border_width), -(2 * border_width)};
|
result = (Rect) {border_width, border_width, -(2 * border_width), -(2 * border_width)};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Floating windows are never adjacent to any other window, so
|
/* Floating windows are never adjacent to any other window, so
|
||||||
don’t hide their border(s). This prevents bug #998. */
|
don’t hide their border(s). This prevents bug #998. */
|
||||||
if (con_is_floating(con))
|
if (con_is_floating(con))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (borders_to_hide & ADJ_LEFT_SCREEN_EDGE) {
|
if (borders_to_hide & ADJ_LEFT_SCREEN_EDGE) {
|
||||||
result.x -= border_width;
|
result.x -= border_width;
|
||||||
@ -1129,7 +1131,6 @@ Rect con_border_style_rect(Con *con) {
|
|||||||
result.height += border_width;
|
result.height += border_width;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1333,7 +1334,8 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
|
|||||||
else {
|
else {
|
||||||
if (parent->layout == L_SPLITH)
|
if (parent->layout == L_SPLITH)
|
||||||
con_set_layout(con, L_SPLITV);
|
con_set_layout(con, L_SPLITV);
|
||||||
else con_set_layout(con, L_SPLITH);
|
else
|
||||||
|
con_set_layout(con, L_SPLITH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (parent->layout == L_STACKED)
|
if (parent->layout == L_STACKED)
|
||||||
@ -1341,7 +1343,8 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
|
|||||||
else if (parent->layout == L_TABBED) {
|
else if (parent->layout == L_TABBED) {
|
||||||
if (strcmp(toggle_mode, "all") == 0)
|
if (strcmp(toggle_mode, "all") == 0)
|
||||||
con_set_layout(con, L_SPLITH);
|
con_set_layout(con, L_SPLITH);
|
||||||
else con_set_layout(con, parent->last_split_layout);
|
else
|
||||||
|
con_set_layout(con, parent->last_split_layout);
|
||||||
} else if (parent->layout == L_SPLITH || parent->layout == L_SPLITV) {
|
} else if (parent->layout == L_SPLITH || parent->layout == L_SPLITV) {
|
||||||
if (strcmp(toggle_mode, "all") == 0) {
|
if (strcmp(toggle_mode, "all") == 0) {
|
||||||
/* When toggling through all modes, we toggle between
|
/* When toggling through all modes, we toggle between
|
||||||
@ -1349,7 +1352,8 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
|
|||||||
* stacked. */
|
* stacked. */
|
||||||
if (parent->layout == L_SPLITH)
|
if (parent->layout == L_SPLITH)
|
||||||
con_set_layout(con, L_SPLITV);
|
con_set_layout(con, L_SPLITV);
|
||||||
else con_set_layout(con, L_STACKED);
|
else
|
||||||
|
con_set_layout(con, L_STACKED);
|
||||||
} else {
|
} else {
|
||||||
con_set_layout(con, L_STACKED);
|
con_set_layout(con, L_STACKED);
|
||||||
}
|
}
|
||||||
@ -1410,7 +1414,7 @@ Rect con_minimum_size(Con *con) {
|
|||||||
|
|
||||||
if (con_is_leaf(con)) {
|
if (con_is_leaf(con)) {
|
||||||
DLOG("leaf node, returning 75x50\n");
|
DLOG("leaf node, returning 75x50\n");
|
||||||
return (Rect){ 0, 0, 75, 50 };
|
return (Rect) {0, 0, 75, 50};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con->type == CT_FLOATING_CON) {
|
if (con->type == CT_FLOATING_CON) {
|
||||||
@ -1422,7 +1426,7 @@ Rect con_minimum_size(Con *con) {
|
|||||||
if (con->layout == L_STACKED || con->layout == L_TABBED) {
|
if (con->layout == L_STACKED || con->layout == L_TABBED) {
|
||||||
uint32_t max_width = 0, max_height = 0, deco_height = 0;
|
uint32_t max_width = 0, max_height = 0, deco_height = 0;
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
Rect min = con_minimum_size(child);
|
Rect min = con_minimum_size(child);
|
||||||
deco_height += child->deco_rect.height;
|
deco_height += child->deco_rect.height;
|
||||||
max_width = max(max_width, min.width);
|
max_width = max(max_width, min.width);
|
||||||
@ -1430,7 +1434,7 @@ Rect con_minimum_size(Con *con) {
|
|||||||
}
|
}
|
||||||
DLOG("stacked/tabbed now, returning %d x %d + deco_rect = %d\n",
|
DLOG("stacked/tabbed now, returning %d x %d + deco_rect = %d\n",
|
||||||
max_width, max_height, deco_height);
|
max_width, max_height, deco_height);
|
||||||
return (Rect){ 0, 0, max_width, max_height + deco_height };
|
return (Rect) {0, 0, max_width, max_height + deco_height};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For horizontal/vertical split containers we sum up the width (h-split)
|
/* For horizontal/vertical split containers we sum up the width (h-split)
|
||||||
@ -1439,7 +1443,7 @@ Rect con_minimum_size(Con *con) {
|
|||||||
if (con_is_split(con)) {
|
if (con_is_split(con)) {
|
||||||
uint32_t width = 0, height = 0;
|
uint32_t width = 0, height = 0;
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
Rect min = con_minimum_size(child);
|
Rect min = con_minimum_size(child);
|
||||||
if (con->layout == L_SPLITH) {
|
if (con->layout == L_SPLITH) {
|
||||||
width += min.width;
|
width += min.width;
|
||||||
@ -1450,7 +1454,7 @@ Rect con_minimum_size(Con *con) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DLOG("split container, returning width = %d x height = %d\n", width, height);
|
DLOG("split container, returning width = %d x height = %d\n", width, height);
|
||||||
return (Rect){ 0, 0, width, height };
|
return (Rect) {0, 0, width, height};
|
||||||
}
|
}
|
||||||
|
|
||||||
ELOG("Unhandled case, type = %d, layout = %d, split = %d\n",
|
ELOG("Unhandled case, type = %d, layout = %d, split = %d\n",
|
||||||
@ -1506,7 +1510,7 @@ bool con_fullscreen_permits_focusing(Con *con) {
|
|||||||
* sufficient to guarantee that change won't leave fullscreen in bad shape. */
|
* sufficient to guarantee that change won't leave fullscreen in bad shape. */
|
||||||
if (fs->fullscreen_mode == CF_OUTPUT &&
|
if (fs->fullscreen_mode == CF_OUTPUT &&
|
||||||
con_get_workspace(con) != con_get_workspace(fs)) {
|
con_get_workspace(con) != con_get_workspace(fs)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow it only if the container to be focused is contained within the
|
/* Allow it only if the container to be focused is contained within the
|
||||||
@ -1534,7 +1538,7 @@ bool con_has_urgent_child(Con *con) {
|
|||||||
|
|
||||||
/* We are not interested in floating windows since they can only be
|
/* We are not interested in floating windows since they can only be
|
||||||
* attached to a workspace → nodes_head instead of focus_head */
|
* attached to a workspace → nodes_head instead of focus_head */
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (con_has_urgent_child(child))
|
if (con_has_urgent_child(child))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1647,12 +1651,12 @@ char *con_get_tree_representation(Con *con) {
|
|||||||
|
|
||||||
/* 2) append representation of children */
|
/* 2) append representation of children */
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
char *child_txt = con_get_tree_representation(child);
|
char *child_txt = con_get_tree_representation(child);
|
||||||
|
|
||||||
char *tmp_buf;
|
char *tmp_buf;
|
||||||
sasprintf(&tmp_buf, "%s%s%s", buf,
|
sasprintf(&tmp_buf, "%s%s%s", buf,
|
||||||
(TAILQ_FIRST(&(con->nodes_head)) == child ? "" : " "), child_txt);
|
(TAILQ_FIRST(&(con->nodes_head)) == child ? "" : " "), child_txt);
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = tmp_buf;
|
buf = tmp_buf;
|
||||||
}
|
}
|
||||||
|
23
src/config.c
23
src/config.c
@ -36,7 +36,7 @@ void ungrab_all_keys(xcb_connection_t *conn) {
|
|||||||
*/
|
*/
|
||||||
void update_barconfig() {
|
void update_barconfig() {
|
||||||
Barconfig *current;
|
Barconfig *current;
|
||||||
TAILQ_FOREACH(current, &barconfigs, configs) {
|
TAILQ_FOREACH (current, &barconfigs, configs) {
|
||||||
ipc_send_barconfig_update_event(current);
|
ipc_send_barconfig_update_event(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,8 +105,7 @@ static char *get_config_path(const char *override_configpath) {
|
|||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
die("Unable to find the configuration file (looked at "
|
die("Unable to find the configuration file (looked at "
|
||||||
"~/.i3/config, $XDG_CONFIG_HOME/i3/config, "
|
"~/.i3/config, $XDG_CONFIG_HOME/i3/config, " SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
|
||||||
SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -196,7 +195,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
|||||||
FREE(barconfig);
|
FREE(barconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear workspace names */
|
/* Clear workspace names */
|
||||||
#if 0
|
#if 0
|
||||||
Workspace *ws;
|
Workspace *ws;
|
||||||
TAILQ_FOREACH(ws, workspaces, workspaces)
|
TAILQ_FOREACH(ws, workspaces, workspaces)
|
||||||
@ -205,7 +204,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
|||||||
|
|
||||||
/* Invalidate pixmap caches in case font or colors changed */
|
/* Invalidate pixmap caches in case font or colors changed */
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons)
|
TAILQ_FOREACH (con, &all_cons, all_cons)
|
||||||
FREE(con->deco_render_params);
|
FREE(con->deco_render_params);
|
||||||
|
|
||||||
/* Get rid of the current font */
|
/* Get rid of the current font */
|
||||||
@ -223,19 +222,19 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
|||||||
bindings = default_mode->bindings;
|
bindings = default_mode->bindings;
|
||||||
|
|
||||||
#define REQUIRED_OPTION(name) \
|
#define REQUIRED_OPTION(name) \
|
||||||
if (config.name == NULL) \
|
if (config.name == NULL) \
|
||||||
die("You did not specify required configuration option " #name "\n");
|
die("You did not specify required configuration option " #name "\n");
|
||||||
|
|
||||||
/* Clear the old config or initialize the data structure */
|
/* Clear the old config or initialize the data structure */
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
|
|
||||||
/* Initialize default colors */
|
/* Initialize default colors */
|
||||||
#define INIT_COLOR(x, cborder, cbackground, ctext, cindicator) \
|
#define INIT_COLOR(x, cborder, cbackground, ctext, cindicator) \
|
||||||
do { \
|
do { \
|
||||||
x.border = get_colorpixel(cborder); \
|
x.border = get_colorpixel(cborder); \
|
||||||
x.background = get_colorpixel(cbackground); \
|
x.background = get_colorpixel(cbackground); \
|
||||||
x.text = get_colorpixel(ctext); \
|
x.text = get_colorpixel(ctext); \
|
||||||
x.indicator = get_colorpixel(cindicator); \
|
x.indicator = get_colorpixel(cindicator); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
config.client.background = get_colorpixel("#000000");
|
config.client.background = get_colorpixel("#000000");
|
||||||
|
@ -68,7 +68,7 @@ CFGFUN(criteria_add, const char *ctype, const char *cvalue) {
|
|||||||
(end && *end != '\0')) {
|
(end && *end != '\0')) {
|
||||||
ELOG("Could not parse con id \"%s\"\n", cvalue);
|
ELOG("Could not parse con id \"%s\"\n", cvalue);
|
||||||
} else {
|
} else {
|
||||||
current_match->con_id = (Con*)parsed;
|
current_match->con_id = (Con *)parsed;
|
||||||
DLOG("id as int = %p\n", current_match->con_id);
|
DLOG("id as int = %p\n", current_match->con_id);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -163,19 +163,18 @@ uint32_t modifiers_from_str(const char *str) {
|
|||||||
static char *font_pattern;
|
static char *font_pattern;
|
||||||
|
|
||||||
CFGFUN(font, const char *font) {
|
CFGFUN(font, const char *font) {
|
||||||
config.font = load_font(font, true);
|
config.font = load_font(font, true);
|
||||||
set_font(&config.font);
|
set_font(&config.font);
|
||||||
|
|
||||||
/* Save the font pattern for using it as bar font later on */
|
/* Save the font pattern for using it as bar font later on */
|
||||||
FREE(font_pattern);
|
FREE(font_pattern);
|
||||||
font_pattern = sstrdup(font);
|
font_pattern = sstrdup(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command) {
|
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command) {
|
||||||
configure_binding(bindtype, modifiers, key, release, command, DEFAULT_BINDING_MODE);
|
configure_binding(bindtype, modifiers, key, release, command, DEFAULT_BINDING_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Mode handling
|
* Mode handling
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -197,14 +196,14 @@ CFGFUN(enter_mode, const char *modename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command) {
|
CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command) {
|
||||||
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
||||||
new->command = sstrdup(command);
|
new->command = sstrdup(command);
|
||||||
new->no_startup_id = (no_startup_id != NULL);
|
new->no_startup_id = (no_startup_id != NULL);
|
||||||
if (strcmp(exectype, "exec") == 0) {
|
if (strcmp(exectype, "exec") == 0) {
|
||||||
TAILQ_INSERT_TAIL(&autostarts, new, autostarts);
|
TAILQ_INSERT_TAIL(&autostarts, new, autostarts);
|
||||||
} else {
|
} else {
|
||||||
TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always);
|
TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(for_window, const char *command) {
|
CFGFUN(for_window, const char *command) {
|
||||||
@ -239,7 +238,8 @@ CFGFUN(default_orientation, const char *orientation) {
|
|||||||
config.default_orientation = HORIZ;
|
config.default_orientation = HORIZ;
|
||||||
else if (strcmp(orientation, "vertical") == 0)
|
else if (strcmp(orientation, "vertical") == 0)
|
||||||
config.default_orientation = VERT;
|
config.default_orientation = VERT;
|
||||||
else config.default_orientation = NO_ORIENTATION;
|
else
|
||||||
|
config.default_orientation = NO_ORIENTATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(workspace_layout, const char *layout) {
|
CFGFUN(workspace_layout, const char *layout) {
|
||||||
@ -248,7 +248,8 @@ CFGFUN(workspace_layout, const char *layout) {
|
|||||||
else if (strcmp(layout, "stacking") == 0 ||
|
else if (strcmp(layout, "stacking") == 0 ||
|
||||||
strcmp(layout, "stacked") == 0)
|
strcmp(layout, "stacked") == 0)
|
||||||
config.default_layout = L_STACKED;
|
config.default_layout = L_STACKED;
|
||||||
else config.default_layout = L_TABBED;
|
else
|
||||||
|
config.default_layout = L_TABBED;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(new_window, const char *windowtype, const char *border, const long width) {
|
CFGFUN(new_window, const char *windowtype, const char *border, const long width) {
|
||||||
@ -291,7 +292,8 @@ CFGFUN(hide_edge_borders, const char *borders) {
|
|||||||
config.hide_edge_borders = ADJ_NONE;
|
config.hide_edge_borders = ADJ_NONE;
|
||||||
else if (eval_boolstr(borders))
|
else if (eval_boolstr(borders))
|
||||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
||||||
else config.hide_edge_borders = ADJ_NONE;
|
else
|
||||||
|
config.hide_edge_borders = ADJ_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(focus_follows_mouse, const char *value) {
|
CFGFUN(focus_follows_mouse, const char *value) {
|
||||||
@ -332,7 +334,7 @@ CFGFUN(workspace, const char *workspace, const char *output) {
|
|||||||
* outputs */
|
* outputs */
|
||||||
struct Workspace_Assignment *assignment;
|
struct Workspace_Assignment *assignment;
|
||||||
bool duplicate = false;
|
bool duplicate = false;
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcasecmp(assignment->name, workspace) == 0) {
|
if (strcasecmp(assignment->name, workspace) == 0) {
|
||||||
ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
|
ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
|
||||||
workspace);
|
workspace);
|
||||||
@ -372,16 +374,16 @@ CFGFUN(color_single, const char *colorclass, const char *color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator) {
|
CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator) {
|
||||||
#define APPLY_COLORS(classname) \
|
#define APPLY_COLORS(classname) \
|
||||||
do { \
|
do { \
|
||||||
if (strcmp(colorclass, "client." #classname) == 0) { \
|
if (strcmp(colorclass, "client." #classname) == 0) { \
|
||||||
config.client.classname.border = get_colorpixel(border); \
|
config.client.classname.border = get_colorpixel(border); \
|
||||||
config.client.classname.background = get_colorpixel(background); \
|
config.client.classname.background = get_colorpixel(background); \
|
||||||
config.client.classname.text = get_colorpixel(text); \
|
config.client.classname.text = get_colorpixel(text); \
|
||||||
if (indicator != NULL) { \
|
if (indicator != NULL) { \
|
||||||
config.client. classname .indicator = get_colorpixel(indicator); \
|
config.client.classname.indicator = get_colorpixel(indicator); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
APPLY_COLORS(focused_inactive);
|
APPLY_COLORS(focused_inactive);
|
||||||
@ -430,7 +432,7 @@ CFGFUN(bar_id, const char *bar_id) {
|
|||||||
|
|
||||||
CFGFUN(bar_output, const char *output) {
|
CFGFUN(bar_output, const char *output) {
|
||||||
int new_outputs = current_bar.num_outputs + 1;
|
int new_outputs = current_bar.num_outputs + 1;
|
||||||
current_bar.outputs = srealloc(current_bar.outputs, sizeof(char*) * new_outputs);
|
current_bar.outputs = srealloc(current_bar.outputs, sizeof(char *) * new_outputs);
|
||||||
current_bar.outputs[current_bar.num_outputs] = sstrdup(output);
|
current_bar.outputs[current_bar.num_outputs] = sstrdup(output);
|
||||||
current_bar.num_outputs = new_outputs;
|
current_bar.num_outputs = new_outputs;
|
||||||
}
|
}
|
||||||
@ -467,20 +469,20 @@ CFGFUN(bar_i3bar_command, const char *i3bar_command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
|
CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
|
||||||
#define APPLY_COLORS(classname) \
|
#define APPLY_COLORS(classname) \
|
||||||
do { \
|
do { \
|
||||||
if (strcmp(colorclass, #classname) == 0) { \
|
if (strcmp(colorclass, #classname) == 0) { \
|
||||||
if (text != NULL) { \
|
if (text != NULL) { \
|
||||||
/* New syntax: border, background, text */ \
|
/* New syntax: border, background, text */ \
|
||||||
current_bar.colors. classname ## _border = sstrdup(border); \
|
current_bar.colors.classname##_border = sstrdup(border); \
|
||||||
current_bar.colors. classname ## _bg = sstrdup(background); \
|
current_bar.colors.classname##_bg = sstrdup(background); \
|
||||||
current_bar.colors. classname ## _text = sstrdup(text); \
|
current_bar.colors.classname##_text = sstrdup(text); \
|
||||||
} else { \
|
} else { \
|
||||||
/* Old syntax: text, background */ \
|
/* Old syntax: text, background */ \
|
||||||
current_bar.colors. classname ## _bg = sstrdup(background); \
|
current_bar.colors.classname##_bg = sstrdup(background); \
|
||||||
current_bar.colors. classname ## _text = sstrdup(border); \
|
current_bar.colors.classname##_text = sstrdup(border); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
APPLY_COLORS(focused_workspace);
|
APPLY_COLORS(focused_workspace);
|
||||||
|
@ -39,8 +39,8 @@
|
|||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
// Macros to make the YAJL API a bit easier to use.
|
// Macros to make the YAJL API a bit easier to use.
|
||||||
#define y(x, ...) yajl_gen_ ## x (command_output.json_gen, ##__VA_ARGS__)
|
#define y(x, ...) yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__)
|
||||||
#define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char*)str, strlen(str))
|
#define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str))
|
||||||
|
|
||||||
#ifndef TEST_PARSER
|
#ifndef TEST_PARSER
|
||||||
pid_t config_error_nagbar_pid = -1;
|
pid_t config_error_nagbar_pid = -1;
|
||||||
@ -146,7 +146,6 @@ static void push_long(const char *identifier, long num) {
|
|||||||
"in the code, or a new command which contains more than "
|
"in the code, or a new command which contains more than "
|
||||||
"10 identified tokens.\n");
|
"10 identified tokens.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_string(const char *identifier) {
|
static const char *get_string(const char *identifier) {
|
||||||
@ -240,18 +239,17 @@ static struct ConfigResultIR command_output;
|
|||||||
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
||||||
* (likewise for other states, e.g. MODE or BAR).
|
* (likewise for other states, e.g. MODE or BAR).
|
||||||
* This list is used to process the nearest error token. */
|
* This list is used to process the nearest error token. */
|
||||||
static cmdp_state statelist[10] = { INITIAL };
|
static cmdp_state statelist[10] = {INITIAL};
|
||||||
/* NB: statelist_idx points to where the next entry will be inserted */
|
/* NB: statelist_idx points to where the next entry will be inserted */
|
||||||
static int statelist_idx = 1;
|
static int statelist_idx = 1;
|
||||||
|
|
||||||
#include "GENERATED_config_call.h"
|
#include "GENERATED_config_call.h"
|
||||||
|
|
||||||
|
|
||||||
static void next_state(const cmdp_token *token) {
|
static void next_state(const cmdp_token *token) {
|
||||||
cmdp_state _next_state = token->next_state;
|
cmdp_state _next_state = token->next_state;
|
||||||
|
|
||||||
//printf("token = name %s identifier %s\n", token->name, token->identifier);
|
//printf("token = name %s identifier %s\n", token->name, token->identifier);
|
||||||
//printf("next_state = %d\n", token->next_state);
|
//printf("next_state = %d\n", token->next_state);
|
||||||
if (token->next_state == __CALL) {
|
if (token->next_state == __CALL) {
|
||||||
subcommand_output.json_gen = command_output.json_gen;
|
subcommand_output.json_gen = command_output.json_gen;
|
||||||
GENERATED_call(token->extra.call_identifier, &subcommand_output);
|
GENERATED_call(token->extra.call_identifier, &subcommand_output);
|
||||||
@ -269,7 +267,7 @@ static void next_state(const cmdp_token *token) {
|
|||||||
for (int i = 0; i < statelist_idx; i++) {
|
for (int i = 0; i < statelist_idx; i++) {
|
||||||
if (statelist[i] != _next_state)
|
if (statelist[i] != _next_state)
|
||||||
continue;
|
continue;
|
||||||
statelist_idx = i+1;
|
statelist_idx = i + 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +333,7 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
bool token_handled;
|
bool token_handled;
|
||||||
linecnt = 1;
|
linecnt = 1;
|
||||||
|
|
||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
#ifndef TEST_PARSER
|
#ifndef TEST_PARSER
|
||||||
cfg_criteria_init(¤t_match, &subcommand_output, INITIAL);
|
cfg_criteria_init(¤t_match, &subcommand_output, INITIAL);
|
||||||
#endif
|
#endif
|
||||||
@ -348,7 +346,7 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
|
|
||||||
//printf("remaining input: %s\n", walk);
|
//printf("remaining input: %s\n", walk);
|
||||||
|
|
||||||
cmdp_token_ptr *ptr = &(tokens[state]);
|
cmdp_token_ptr *ptr = &(tokens[state]);
|
||||||
token_handled = false;
|
token_handled = false;
|
||||||
@ -398,7 +396,7 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
if (*walk == '"') {
|
if (*walk == '"') {
|
||||||
beginning++;
|
beginning++;
|
||||||
walk++;
|
walk++;
|
||||||
while (*walk != '\0' && (*walk != '"' || *(walk-1) == '\\'))
|
while (*walk != '\0' && (*walk != '"' || *(walk - 1) == '\\'))
|
||||||
walk++;
|
walk++;
|
||||||
} else {
|
} else {
|
||||||
if (token->name[0] == 's') {
|
if (token->name[0] == 's') {
|
||||||
@ -410,22 +408,22 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
* semicolon (;). */
|
* semicolon (;). */
|
||||||
while (*walk != ' ' && *walk != '\t' &&
|
while (*walk != ' ' && *walk != '\t' &&
|
||||||
*walk != ']' && *walk != ',' &&
|
*walk != ']' && *walk != ',' &&
|
||||||
*walk != ';' && *walk != '\r' &&
|
*walk != ';' && *walk != '\r' &&
|
||||||
*walk != '\n' && *walk != '\0')
|
*walk != '\n' && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (walk != beginning) {
|
if (walk != beginning) {
|
||||||
char *str = scalloc(walk-beginning + 1);
|
char *str = scalloc(walk - beginning + 1);
|
||||||
/* We copy manually to handle escaping of characters. */
|
/* We copy manually to handle escaping of characters. */
|
||||||
int inpos, outpos;
|
int inpos, outpos;
|
||||||
for (inpos = 0, outpos = 0;
|
for (inpos = 0, outpos = 0;
|
||||||
inpos < (walk-beginning);
|
inpos < (walk - beginning);
|
||||||
inpos++, outpos++) {
|
inpos++, outpos++) {
|
||||||
/* We only handle escaped double quotes to not break
|
/* We only handle escaped double quotes to not break
|
||||||
* backwards compatibility with people using \w in
|
* backwards compatibility with people using \w in
|
||||||
* regular expressions etc. */
|
* regular expressions etc. */
|
||||||
if (beginning[inpos] == '\\' && beginning[inpos+1] == '"')
|
if (beginning[inpos] == '\\' && beginning[inpos + 1] == '"')
|
||||||
inpos++;
|
inpos++;
|
||||||
str[outpos] = beginning[inpos];
|
str[outpos] = beginning[inpos];
|
||||||
}
|
}
|
||||||
@ -443,13 +441,13 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(token->name, "line") == 0) {
|
if (strcmp(token->name, "line") == 0) {
|
||||||
while (*walk != '\0' && *walk != '\n' && *walk != '\r')
|
while (*walk != '\0' && *walk != '\n' && *walk != '\r')
|
||||||
walk++;
|
walk++;
|
||||||
next_state(token);
|
next_state(token);
|
||||||
token_handled = true;
|
token_handled = true;
|
||||||
linecnt++;
|
linecnt++;
|
||||||
walk++;
|
walk++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(token->name, "end") == 0) {
|
if (strcmp(token->name, "end") == 0) {
|
||||||
@ -457,19 +455,19 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
if (*walk == '\0' || *walk == '\n' || *walk == '\r') {
|
if (*walk == '\0' || *walk == '\n' || *walk == '\r') {
|
||||||
next_state(token);
|
next_state(token);
|
||||||
token_handled = true;
|
token_handled = true;
|
||||||
/* To make sure we start with an appropriate matching
|
/* To make sure we start with an appropriate matching
|
||||||
* datastructure for commands which do *not* specify any
|
* datastructure for commands which do *not* specify any
|
||||||
* criteria, we re-initialize the criteria system after
|
* criteria, we re-initialize the criteria system after
|
||||||
* every command. */
|
* every command. */
|
||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
#ifndef TEST_PARSER
|
#ifndef TEST_PARSER
|
||||||
cfg_criteria_init(¤t_match, &subcommand_output, INITIAL);
|
cfg_criteria_init(¤t_match, &subcommand_output, INITIAL);
|
||||||
#endif
|
#endif
|
||||||
linecnt++;
|
linecnt++;
|
||||||
walk++;
|
walk++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!token_handled) {
|
if (!token_handled) {
|
||||||
@ -516,7 +514,6 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
possible_tokens);
|
possible_tokens);
|
||||||
free(possible_tokens);
|
free(possible_tokens);
|
||||||
|
|
||||||
|
|
||||||
/* Go back to the beginning of the line */
|
/* Go back to the beginning of the line */
|
||||||
const char *error_line = start_of_line(walk, input);
|
const char *error_line = start_of_line(walk, input);
|
||||||
|
|
||||||
@ -536,10 +533,10 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
|
|
||||||
/* Print context lines *before* the error, if any. */
|
/* Print context lines *before* the error, if any. */
|
||||||
if (linecnt > 1) {
|
if (linecnt > 1) {
|
||||||
const char *context_p1_start = start_of_line(error_line-2, input);
|
const char *context_p1_start = start_of_line(error_line - 2, input);
|
||||||
char *context_p1_line = single_line(context_p1_start);
|
char *context_p1_line = single_line(context_p1_start);
|
||||||
if (linecnt > 2) {
|
if (linecnt > 2) {
|
||||||
const char *context_p2_start = start_of_line(context_p1_start-2, input);
|
const char *context_p2_start = start_of_line(context_p1_start - 2, input);
|
||||||
char *context_p2_line = single_line(context_p2_start);
|
char *context_p2_line = single_line(context_p2_start);
|
||||||
ELOG("CONFIG: Line %3d: %s\n", linecnt - 2, context_p2_line);
|
ELOG("CONFIG: Line %3d: %s\n", linecnt - 2, context_p2_line);
|
||||||
free(context_p2_line);
|
free(context_p2_line);
|
||||||
@ -592,7 +589,7 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context)
|
|||||||
* we find the nearest state which contains an <error> token
|
* we find the nearest state which contains an <error> token
|
||||||
* and follow that one. */
|
* and follow that one. */
|
||||||
bool error_token_found = false;
|
bool error_token_found = false;
|
||||||
for (int i = statelist_idx-1; (i >= 0) && !error_token_found; i--) {
|
for (int i = statelist_idx - 1; (i >= 0) && !error_token_found; i--) {
|
||||||
cmdp_token_ptr *errptr = &(tokens[statelist[i]]);
|
cmdp_token_ptr *errptr = &(tokens[statelist[i]]);
|
||||||
for (int j = 0; j < errptr->n; j++) {
|
for (int j = 0; j < errptr->n; j++) {
|
||||||
if (strcmp(errptr->array[j].name, "error") != 0)
|
if (strcmp(errptr->array[j].name, "error") != 0)
|
||||||
@ -687,7 +684,7 @@ static int detect_version(char *buf) {
|
|||||||
strncasecmp(line, "force_focus_wrapping", strlen("force_focus_wrapping")) == 0 ||
|
strncasecmp(line, "force_focus_wrapping", strlen("force_focus_wrapping")) == 0 ||
|
||||||
strncasecmp(line, "# i3 config file (v4)", strlen("# i3 config file (v4)")) == 0 ||
|
strncasecmp(line, "# i3 config file (v4)", strlen("# i3 config file (v4)")) == 0 ||
|
||||||
strncasecmp(line, "workspace_layout", strlen("workspace_layout")) == 0) {
|
strncasecmp(line, "workspace_layout", strlen("workspace_layout")) == 0) {
|
||||||
LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk-line), line);
|
LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk - line), line);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,12 +716,12 @@ static int detect_version(char *buf) {
|
|||||||
strncasecmp(bind, "border borderless", strlen("border borderless")) == 0 ||
|
strncasecmp(bind, "border borderless", strlen("border borderless")) == 0 ||
|
||||||
strncasecmp(bind, "--no-startup-id", strlen("--no-startup-id")) == 0 ||
|
strncasecmp(bind, "--no-startup-id", strlen("--no-startup-id")) == 0 ||
|
||||||
strncasecmp(bind, "bar", strlen("bar")) == 0) {
|
strncasecmp(bind, "bar", strlen("bar")) == 0) {
|
||||||
LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk-line), line);
|
LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk - line), line);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
/* advance to the next line */
|
/* advance to the next line */
|
||||||
walk++;
|
walk++;
|
||||||
line = walk;
|
line = walk;
|
||||||
@ -770,8 +767,7 @@ static char *migrate_config(char *input, off_t size) {
|
|||||||
|
|
||||||
static char *argv[] = {
|
static char *argv[] = {
|
||||||
NULL, /* will be replaced by the executable path */
|
NULL, /* will be replaced by the executable path */
|
||||||
NULL
|
NULL};
|
||||||
};
|
|
||||||
exec_i3_utility("i3-migrate-config-to-v4", argv);
|
exec_i3_utility("i3-migrate-config-to-v4", argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,12 +917,12 @@ void parse_file(const char *f) {
|
|||||||
* variables (otherwise we will count them twice, which is bad when
|
* variables (otherwise we will count them twice, which is bad when
|
||||||
* 'extra' is negative) */
|
* 'extra' is negative) */
|
||||||
char *bufcopy = sstrdup(buf);
|
char *bufcopy = sstrdup(buf);
|
||||||
SLIST_FOREACH(current, &variables, variables) {
|
SLIST_FOREACH (current, &variables, variables) {
|
||||||
int extra = (strlen(current->value) - strlen(current->key));
|
int extra = (strlen(current->value) - strlen(current->key));
|
||||||
char *next;
|
char *next;
|
||||||
for (next = bufcopy;
|
for (next = bufcopy;
|
||||||
next < (bufcopy + stbuf.st_size) &&
|
next < (bufcopy + stbuf.st_size) &&
|
||||||
(next = strcasestr(next, current->key)) != NULL;
|
(next = strcasestr(next, current->key)) != NULL;
|
||||||
next += strlen(current->key)) {
|
next += strlen(current->key)) {
|
||||||
*next = '_';
|
*next = '_';
|
||||||
extra_bytes += extra;
|
extra_bytes += extra;
|
||||||
@ -941,11 +937,11 @@ void parse_file(const char *f) {
|
|||||||
destwalk = new;
|
destwalk = new;
|
||||||
while (walk < (buf + stbuf.st_size)) {
|
while (walk < (buf + stbuf.st_size)) {
|
||||||
/* Find the next variable */
|
/* Find the next variable */
|
||||||
SLIST_FOREACH(current, &variables, variables)
|
SLIST_FOREACH (current, &variables, variables)
|
||||||
current->next_match = strcasestr(walk, current->key);
|
current->next_match = strcasestr(walk, current->key);
|
||||||
nearest = NULL;
|
nearest = NULL;
|
||||||
int distance = stbuf.st_size;
|
int distance = stbuf.st_size;
|
||||||
SLIST_FOREACH(current, &variables, variables) {
|
SLIST_FOREACH (current, &variables, variables) {
|
||||||
if (current->next_match == NULL)
|
if (current->next_match == NULL)
|
||||||
continue;
|
continue;
|
||||||
if ((current->next_match - walk) < distance) {
|
if ((current->next_match - walk) < distance) {
|
||||||
@ -996,7 +992,6 @@ void parse_file(const char *f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
context = scalloc(sizeof(struct context));
|
context = scalloc(sizeof(struct context));
|
||||||
context->filename = f;
|
context->filename = f;
|
||||||
|
|
||||||
@ -1011,7 +1006,7 @@ void parse_file(const char *f) {
|
|||||||
ELOG("Please convert your configfile first, then fix any remaining errors (see above).\n");
|
ELOG("Please convert your configfile first, then fix any remaining errors (see above).\n");
|
||||||
|
|
||||||
char *editaction,
|
char *editaction,
|
||||||
*pageraction;
|
*pageraction;
|
||||||
sasprintf(&editaction, "i3-sensible-editor \"%s\" && i3-msg reload\n", f);
|
sasprintf(&editaction, "i3-sensible-editor \"%s\" && i3-msg reload\n", f);
|
||||||
sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
|
sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
|
||||||
char *argv[] = {
|
char *argv[] = {
|
||||||
@ -1021,17 +1016,14 @@ void parse_file(const char *f) {
|
|||||||
"-t",
|
"-t",
|
||||||
(context->has_errors ? "error" : "warning"),
|
(context->has_errors ? "error" : "warning"),
|
||||||
"-m",
|
"-m",
|
||||||
(context->has_errors ?
|
(context->has_errors ? "You have an error in your i3 config file!" : "Your config is outdated. Please fix the warnings to make sure everything works."),
|
||||||
"You have an error in your i3 config file!" :
|
|
||||||
"Your config is outdated. Please fix the warnings to make sure everything works."),
|
|
||||||
"-b",
|
"-b",
|
||||||
"edit config",
|
"edit config",
|
||||||
editaction,
|
editaction,
|
||||||
(errorfilename ? "-b" : NULL),
|
(errorfilename ? "-b" : NULL),
|
||||||
(context->has_errors ? "show errors" : "show warnings"),
|
(context->has_errors ? "show errors" : "show warnings"),
|
||||||
pageraction,
|
pageraction,
|
||||||
NULL
|
NULL};
|
||||||
};
|
|
||||||
|
|
||||||
start_nagbar(&config_error_nagbar_pid, argv);
|
start_nagbar(&config_error_nagbar_pid, argv);
|
||||||
free(editaction);
|
free(editaction);
|
||||||
|
40
src/debug.c
40
src/debug.c
@ -216,28 +216,28 @@ int format_event(xcb_generic_event_t *e) {
|
|||||||
|
|
||||||
sendEvent = (e->response_type & 0x80) ? 1 : 0;
|
sendEvent = (e->response_type & 0x80) ? 1 : 0;
|
||||||
e->response_type &= ~0x80;
|
e->response_type &= ~0x80;
|
||||||
seqnum = *((uint16_t *) e + 1);
|
seqnum = *((uint16_t *)e + 1);
|
||||||
|
|
||||||
switch(e->response_type) {
|
switch (e->response_type) {
|
||||||
case 0:
|
case 0:
|
||||||
DLOG("Error %s on seqnum %d (%s).\n",
|
DLOG("Error %s on seqnum %d (%s).\n",
|
||||||
labelError[*((uint8_t *) e + 1)],
|
labelError[*((uint8_t *)e + 1)],
|
||||||
seqnum,
|
seqnum,
|
||||||
labelRequest[*((uint8_t *) e + 10)]);
|
labelRequest[*((uint8_t *)e + 10)]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (e->response_type > sizeof(labelEvent) / sizeof(char*))
|
if (e->response_type > sizeof(labelEvent) / sizeof(char *))
|
||||||
break;
|
break;
|
||||||
DLOG("Event %s following seqnum %d%s.\n",
|
DLOG("Event %s following seqnum %d%s.\n",
|
||||||
labelEvent[e->response_type],
|
labelEvent[e->response_type],
|
||||||
seqnum,
|
seqnum,
|
||||||
labelSendEvent[sendEvent]);
|
labelSendEvent[sendEvent]);
|
||||||
break;
|
break;
|
||||||
case XCB_KEYMAP_NOTIFY:
|
case XCB_KEYMAP_NOTIFY:
|
||||||
DLOG("Event %s%s.\n",
|
DLOG("Event %s%s.\n",
|
||||||
labelEvent[e->response_type],
|
labelEvent[e->response_type],
|
||||||
labelSendEvent[sendEvent]);
|
labelSendEvent[sendEvent]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -29,7 +29,7 @@ static int version_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
|
|
||||||
static int version_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
static int version_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
||||||
human_readable_key = (stringlen == strlen("human_readable") &&
|
human_readable_key = (stringlen == strlen("human_readable") &&
|
||||||
strncmp((const char*)stringval, "human_readable", strlen("human_readable")) == 0);
|
strncmp((const char *)stringval, "human_readable", strlen("human_readable")) == 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +76,11 @@ void display_running_version(void) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
err(EXIT_FAILURE, "Could not connect to i3");
|
err(EXIT_FAILURE, "Could not connect to i3");
|
||||||
|
|
||||||
if (ipc_send_message(sockfd, 0, I3_IPC_MESSAGE_TYPE_GET_VERSION,
|
if (ipc_send_message(sockfd, 0, I3_IPC_MESSAGE_TYPE_GET_VERSION,
|
||||||
(uint8_t*)"") == -1)
|
(uint8_t *)"") == -1)
|
||||||
err(EXIT_FAILURE, "IPC: write()");
|
err(EXIT_FAILURE, "IPC: write()");
|
||||||
|
|
||||||
uint32_t reply_length;
|
uint32_t reply_length;
|
||||||
@ -98,7 +98,7 @@ void display_running_version(void) {
|
|||||||
|
|
||||||
yajl_handle handle = yajl_alloc(&version_callbacks, NULL, NULL);
|
yajl_handle handle = yajl_alloc(&version_callbacks, NULL, NULL);
|
||||||
|
|
||||||
yajl_status state = yajl_parse(handle, (const unsigned char*)reply, (int)reply_length);
|
yajl_status state = yajl_parse(handle, (const unsigned char *)reply, (int)reply_length);
|
||||||
if (state != yajl_status_ok)
|
if (state != yajl_status_ok)
|
||||||
errx(EXIT_FAILURE, "Could not parse my own reply. That's weird. reply is %.*s", (int)reply_length, reply);
|
errx(EXIT_FAILURE, "Could not parse my own reply. That's weird. reply is %.*s", (int)reply_length, reply);
|
||||||
|
|
||||||
@ -113,8 +113,8 @@ void display_running_version(void) {
|
|||||||
sasprintf(&exepath, "/proc/%d/exe", getpid());
|
sasprintf(&exepath, "/proc/%d/exe", getpid());
|
||||||
|
|
||||||
while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
|
while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
|
||||||
destpath_size = destpath_size * 2;
|
destpath_size = destpath_size * 2;
|
||||||
destpath = srealloc(destpath, destpath_size);
|
destpath = srealloc(destpath, destpath_size);
|
||||||
}
|
}
|
||||||
if (linksize == -1)
|
if (linksize == -1)
|
||||||
err(EXIT_FAILURE, "readlink(%s)", exepath);
|
err(EXIT_FAILURE, "readlink(%s)", exepath);
|
||||||
|
22
src/ewmh.c
22
src/ewmh.c
@ -24,15 +24,15 @@ void ewmh_update_current_desktop(void) {
|
|||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
/* We count to get the index of this workspace because named workspaces
|
/* We count to get the index of this workspace because named workspaces
|
||||||
* don’t have the ->num property */
|
* don’t have the ->num property */
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
Con *ws;
|
Con *ws;
|
||||||
TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
|
TAILQ_FOREACH (ws, &(output_get_content(output)->nodes_head), nodes) {
|
||||||
if (STARTS_WITH(ws->name, "__"))
|
if (STARTS_WITH(ws->name, "__"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ws == focused_ws) {
|
if (ws == focused_ws) {
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
||||||
A__NET_CURRENT_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &idx);
|
A__NET_CURRENT_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &idx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
++idx;
|
++idx;
|
||||||
@ -49,7 +49,7 @@ void ewmh_update_current_desktop(void) {
|
|||||||
*/
|
*/
|
||||||
void ewmh_update_active_window(xcb_window_t window) {
|
void ewmh_update_active_window(xcb_window_t window) {
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
||||||
A__NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &window);
|
A__NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -109,7 +109,7 @@ void ewmh_update_client_list_stacking(xcb_window_t *stack, int num_windows) {
|
|||||||
*/
|
*/
|
||||||
void ewmh_setup_hints(void) {
|
void ewmh_setup_hints(void) {
|
||||||
xcb_atom_t supported_atoms[] = {
|
xcb_atom_t supported_atoms[] = {
|
||||||
#define xmacro(atom) A_ ## atom,
|
#define xmacro(atom) A_##atom,
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
};
|
};
|
||||||
@ -122,13 +122,13 @@ void ewmh_setup_hints(void) {
|
|||||||
xcb_window_t child_window = xcb_generate_id(conn);
|
xcb_window_t child_window = xcb_generate_id(conn);
|
||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT, /* depth */
|
XCB_COPY_FROM_PARENT, /* depth */
|
||||||
child_window, /* window id */
|
child_window, /* window id */
|
||||||
root, /* parent */
|
root, /* parent */
|
||||||
0, 0, 1, 1, /* dimensions (x, y, w, h) */
|
0, 0, 1, 1, /* dimensions (x, y, w, h) */
|
||||||
0, /* border */
|
0, /* border */
|
||||||
XCB_WINDOW_CLASS_INPUT_ONLY, /* window class */
|
XCB_WINDOW_CLASS_INPUT_ONLY, /* window class */
|
||||||
XCB_COPY_FROM_PARENT, /* visual */
|
XCB_COPY_FROM_PARENT, /* visual */
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
|
||||||
|
@ -20,7 +20,7 @@ static int num_screens;
|
|||||||
*/
|
*/
|
||||||
static Output *get_screen_at(unsigned int x, unsigned int y) {
|
static Output *get_screen_at(unsigned int x, unsigned int y) {
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs)
|
TAILQ_FOREACH (output, &outputs, outputs)
|
||||||
if (output->rect.x == x && output->rect.y == y)
|
if (output->rect.x == x && output->rect.y == y)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
@ -60,7 +60,8 @@ void fake_outputs_init(const char *output_spec) {
|
|||||||
/* We always treat the screen at 0x0 as the primary screen */
|
/* We always treat the screen at 0x0 as the primary screen */
|
||||||
if (new_output->rect.x == 0 && new_output->rect.y == 0)
|
if (new_output->rect.x == 0 && new_output->rect.y == 0)
|
||||||
TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
|
TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
|
||||||
else TAILQ_INSERT_TAIL(&outputs, new_output, outputs);
|
else
|
||||||
|
TAILQ_INSERT_TAIL(&outputs, new_output, outputs);
|
||||||
output_init_con(new_output);
|
output_init_con(new_output);
|
||||||
init_ws_for_output(new_output, output_get_content(new_output->con));
|
init_ws_for_output(new_output, output_get_content(new_output->con));
|
||||||
num_screens++;
|
num_screens++;
|
||||||
|
110
src/floating.c
110
src/floating.c
@ -21,7 +21,7 @@ static Rect total_outputs_dimensions(void) {
|
|||||||
Output *output;
|
Output *output;
|
||||||
/* Use Rect to encapsulate dimensions, ignoring x/y */
|
/* Use Rect to encapsulate dimensions, ignoring x/y */
|
||||||
Rect outputs_dimensions = {0, 0, 0, 0};
|
Rect outputs_dimensions = {0, 0, 0, 0};
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
outputs_dimensions.height += output->rect.height;
|
outputs_dimensions.height += output->rect.height;
|
||||||
outputs_dimensions.width += output->rect.width;
|
outputs_dimensions.width += output->rect.width;
|
||||||
}
|
}
|
||||||
@ -198,14 +198,14 @@ void floating_enable(Con *con, bool automatic) {
|
|||||||
|
|
||||||
DLOG("Original rect: (%d, %d) with %d x %d\n", con->rect.x, con->rect.y, con->rect.width, con->rect.height);
|
DLOG("Original rect: (%d, %d) with %d x %d\n", con->rect.x, con->rect.y, con->rect.width, con->rect.height);
|
||||||
DLOG("Geometry = (%d, %d) with %d x %d\n", con->geometry.x, con->geometry.y, con->geometry.width, con->geometry.height);
|
DLOG("Geometry = (%d, %d) with %d x %d\n", con->geometry.x, con->geometry.y, con->geometry.width, con->geometry.height);
|
||||||
Rect zero = { 0, 0, 0, 0 };
|
Rect zero = {0, 0, 0, 0};
|
||||||
nc->rect = con->geometry;
|
nc->rect = con->geometry;
|
||||||
/* If the geometry was not set (split containers), we need to determine a
|
/* If the geometry was not set (split containers), we need to determine a
|
||||||
* sensible one by combining the geometry of all children */
|
* sensible one by combining the geometry of all children */
|
||||||
if (memcmp(&(nc->rect), &zero, sizeof(Rect)) == 0) {
|
if (memcmp(&(nc->rect), &zero, sizeof(Rect)) == 0) {
|
||||||
DLOG("Geometry not set, combining children\n");
|
DLOG("Geometry not set, combining children\n");
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
DLOG("child geometry: %d x %d\n", child->geometry.width, child->geometry.height);
|
DLOG("child geometry: %d x %d\n", child->geometry.width, child->geometry.height);
|
||||||
nc->rect.width += child->geometry.width;
|
nc->rect.width += child->geometry.width;
|
||||||
nc->rect.height = max(nc->rect.height, child->geometry.height);
|
nc->rect.height = max(nc->rect.height, child->geometry.height);
|
||||||
@ -231,7 +231,7 @@ void floating_enable(Con *con, bool automatic) {
|
|||||||
nc->rect.width -= border_style_rect.width;
|
nc->rect.width -= border_style_rect.width;
|
||||||
|
|
||||||
/* Add some more pixels for the title bar */
|
/* Add some more pixels for the title bar */
|
||||||
if(con_border_style(con) == BS_NORMAL)
|
if (con_border_style(con) == BS_NORMAL)
|
||||||
nc->rect.height += deco_height;
|
nc->rect.height += deco_height;
|
||||||
|
|
||||||
/* Honor the X11 border */
|
/* Honor the X11 border */
|
||||||
@ -258,7 +258,8 @@ void floating_enable(Con *con, bool automatic) {
|
|||||||
/* Sanity check: Are the coordinates on the appropriate output? If not, we
|
/* Sanity check: Are the coordinates on the appropriate output? If not, we
|
||||||
* need to change them */
|
* need to change them */
|
||||||
Output *current_output = get_output_containing(nc->rect.x +
|
Output *current_output = get_output_containing(nc->rect.x +
|
||||||
(nc->rect.width / 2), nc->rect.y + (nc->rect.height / 2));
|
(nc->rect.width / 2),
|
||||||
|
nc->rect.y + (nc->rect.height / 2));
|
||||||
|
|
||||||
Con *correct_output = con_get_output(ws);
|
Con *correct_output = con_get_output(ws);
|
||||||
if (!current_output || current_output->con != correct_output) {
|
if (!current_output || current_output->con != correct_output) {
|
||||||
@ -336,7 +337,8 @@ void floating_disable(Con *con, bool automatic) {
|
|||||||
* workspace itself */
|
* workspace itself */
|
||||||
if (focused->type == CT_WORKSPACE)
|
if (focused->type == CT_WORKSPACE)
|
||||||
con->parent = focused;
|
con->parent = focused;
|
||||||
else con->parent = focused->parent;
|
else
|
||||||
|
con->parent = focused->parent;
|
||||||
|
|
||||||
/* con_fix_percent will adjust the percent value */
|
/* con_fix_percent will adjust the percent value */
|
||||||
con->percent = 0.0;
|
con->percent = 0.0;
|
||||||
@ -481,25 +483,27 @@ DRAGGING_CB(resize_window_callback) {
|
|||||||
uint32_t dest_width;
|
uint32_t dest_width;
|
||||||
uint32_t dest_height;
|
uint32_t dest_height;
|
||||||
|
|
||||||
double ratio = (double) old_rect->width / old_rect->height;
|
double ratio = (double)old_rect->width / old_rect->height;
|
||||||
|
|
||||||
/* First guess: We resize by exactly the amount the mouse moved,
|
/* First guess: We resize by exactly the amount the mouse moved,
|
||||||
* taking into account in which corner the client was grabbed */
|
* taking into account in which corner the client was grabbed */
|
||||||
if (corner & BORDER_LEFT)
|
if (corner & BORDER_LEFT)
|
||||||
dest_width = old_rect->width - (new_x - event->root_x);
|
dest_width = old_rect->width - (new_x - event->root_x);
|
||||||
else dest_width = old_rect->width + (new_x - event->root_x);
|
else
|
||||||
|
dest_width = old_rect->width + (new_x - event->root_x);
|
||||||
|
|
||||||
if (corner & BORDER_TOP)
|
if (corner & BORDER_TOP)
|
||||||
dest_height = old_rect->height - (new_y - event->root_y);
|
dest_height = old_rect->height - (new_y - event->root_y);
|
||||||
else dest_height = old_rect->height + (new_y - event->root_y);
|
else
|
||||||
|
dest_height = old_rect->height + (new_y - event->root_y);
|
||||||
|
|
||||||
/* User wants to keep proportions, so we may have to adjust our values */
|
/* User wants to keep proportions, so we may have to adjust our values */
|
||||||
if (params->proportional) {
|
if (params->proportional) {
|
||||||
dest_width = max(dest_width, (int) (dest_height * ratio));
|
dest_width = max(dest_width, (int)(dest_height * ratio));
|
||||||
dest_height = max(dest_height, (int) (dest_width / ratio));
|
dest_height = max(dest_height, (int)(dest_width / ratio));
|
||||||
}
|
}
|
||||||
|
|
||||||
con->rect = (Rect) { dest_x, dest_y, dest_width, dest_height };
|
con->rect = (Rect) {dest_x, dest_y, dest_width, dest_height};
|
||||||
|
|
||||||
/* Obey window size */
|
/* Obey window size */
|
||||||
floating_check_size(con);
|
floating_check_size(con);
|
||||||
@ -537,21 +541,19 @@ void floating_resize_window(Con *con, const bool proportional,
|
|||||||
|
|
||||||
if (event->event_x <= (int16_t)(con->rect.width / 2))
|
if (event->event_x <= (int16_t)(con->rect.width / 2))
|
||||||
corner |= BORDER_LEFT;
|
corner |= BORDER_LEFT;
|
||||||
else corner |= BORDER_RIGHT;
|
else
|
||||||
|
corner |= BORDER_RIGHT;
|
||||||
|
|
||||||
int cursor = 0;
|
int cursor = 0;
|
||||||
if (event->event_y <= (int16_t)(con->rect.height / 2)) {
|
if (event->event_y <= (int16_t)(con->rect.height / 2)) {
|
||||||
corner |= BORDER_TOP;
|
corner |= BORDER_TOP;
|
||||||
cursor = (corner & BORDER_LEFT) ?
|
cursor = (corner & BORDER_LEFT) ? XCURSOR_CURSOR_TOP_LEFT_CORNER : XCURSOR_CURSOR_TOP_RIGHT_CORNER;
|
||||||
XCURSOR_CURSOR_TOP_LEFT_CORNER : XCURSOR_CURSOR_TOP_RIGHT_CORNER;
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
corner |= BORDER_BOTTOM;
|
corner |= BORDER_BOTTOM;
|
||||||
cursor = (corner & BORDER_LEFT) ?
|
cursor = (corner & BORDER_LEFT) ? XCURSOR_CURSOR_BOTTOM_LEFT_CORNER : XCURSOR_CURSOR_BOTTOM_RIGHT_CORNER;
|
||||||
XCURSOR_CURSOR_BOTTOM_LEFT_CORNER : XCURSOR_CURSOR_BOTTOM_RIGHT_CORNER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct resize_window_callback_params params = { corner, proportional, event };
|
struct resize_window_callback_params params = {corner, proportional, event};
|
||||||
|
|
||||||
/* get the initial rect in case of revert/cancel */
|
/* get the initial rect in case of revert/cancel */
|
||||||
Rect initial_rect = con->rect;
|
Rect initial_rect = con->rect;
|
||||||
@ -589,13 +591,13 @@ struct drag_x11_cb {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
struct drag_x11_cb *dragloop = (struct drag_x11_cb*)w;
|
struct drag_x11_cb *dragloop = (struct drag_x11_cb *)w;
|
||||||
xcb_motion_notify_event_t *last_motion_notify = NULL;
|
xcb_motion_notify_event_t *last_motion_notify = NULL;
|
||||||
xcb_generic_event_t *event;
|
xcb_generic_event_t *event;
|
||||||
|
|
||||||
while ((event = xcb_poll_for_event(conn)) != NULL) {
|
while ((event = xcb_poll_for_event(conn)) != NULL) {
|
||||||
if (event->response_type == 0) {
|
if (event->response_type == 0) {
|
||||||
xcb_generic_error_t *error = (xcb_generic_error_t*)event;
|
xcb_generic_error_t *error = (xcb_generic_error_t *)event;
|
||||||
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
||||||
error->sequence, error->error_code);
|
error->sequence, error->error_code);
|
||||||
free(event);
|
free(event);
|
||||||
@ -617,7 +619,7 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_UNMAP_NOTIFY: {
|
case XCB_UNMAP_NOTIFY: {
|
||||||
xcb_unmap_notify_event_t *unmap_event = (xcb_unmap_notify_event_t*)event;
|
xcb_unmap_notify_event_t *unmap_event = (xcb_unmap_notify_event_t *)event;
|
||||||
Con *con = con_by_window_id(unmap_event->window);
|
Con *con = con_by_window_id(unmap_event->window);
|
||||||
|
|
||||||
if (con != NULL) {
|
if (con != NULL) {
|
||||||
@ -636,7 +638,7 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
case XCB_MOTION_NOTIFY:
|
case XCB_MOTION_NOTIFY:
|
||||||
/* motion_notify events are saved for later */
|
/* motion_notify events are saved for later */
|
||||||
FREE(last_motion_notify);
|
FREE(last_motion_notify);
|
||||||
last_motion_notify = (xcb_motion_notify_event_t*)event;
|
last_motion_notify = (xcb_motion_notify_event_t *)event;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -645,7 +647,7 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_motion_notify != (xcb_motion_notify_event_t*)event)
|
if (last_motion_notify != (xcb_motion_notify_event_t *)event)
|
||||||
free(event);
|
free(event);
|
||||||
|
|
||||||
if (dragloop->result != DRAGGING)
|
if (dragloop->result != DRAGGING)
|
||||||
@ -656,15 +658,14 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
dragloop->callback(
|
dragloop->callback(
|
||||||
dragloop->con,
|
dragloop->con,
|
||||||
&(dragloop->old_rect),
|
&(dragloop->old_rect),
|
||||||
last_motion_notify->root_x,
|
last_motion_notify->root_x,
|
||||||
last_motion_notify->root_y,
|
last_motion_notify->root_y,
|
||||||
dragloop->extra);
|
dragloop->extra);
|
||||||
free(last_motion_notify);
|
free(last_motion_notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function grabs your pointer and keyboard and lets you drag stuff around
|
* This function grabs your pointer and keyboard and lets you drag stuff around
|
||||||
* (borders). Every time you move your mouse, an XCB_MOTION_NOTIFY event will
|
* (borders). Every time you move your mouse, an XCB_MOTION_NOTIFY event will
|
||||||
@ -674,10 +675,9 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
|
drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
|
||||||
confine_to, border_t border, int cursor, callback_t callback, const void *extra)
|
confine_to,
|
||||||
{
|
border_t border, int cursor, callback_t callback, const void *extra) {
|
||||||
xcb_cursor_t xcursor = (cursor && xcursor_supported) ?
|
xcb_cursor_t xcursor = (cursor && xcursor_supported) ? xcursor_get_cursor(cursor) : XCB_NONE;
|
||||||
xcursor_get_cursor(cursor) : XCB_NONE;
|
|
||||||
|
|
||||||
/* Grab the pointer */
|
/* Grab the pointer */
|
||||||
xcb_grab_pointer_cookie_t cookie;
|
xcb_grab_pointer_cookie_t cookie;
|
||||||
@ -685,14 +685,14 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_
|
|||||||
xcb_generic_error_t *error;
|
xcb_generic_error_t *error;
|
||||||
|
|
||||||
cookie = xcb_grab_pointer(conn,
|
cookie = xcb_grab_pointer(conn,
|
||||||
false, /* get all pointer events specified by the following mask */
|
false, /* get all pointer events specified by the following mask */
|
||||||
root, /* grab the root window */
|
root, /* grab the root window */
|
||||||
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION, /* which events to let through */
|
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION, /* which events to let through */
|
||||||
XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */
|
XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */
|
||||||
XCB_GRAB_MODE_ASYNC, /* keyboard mode */
|
XCB_GRAB_MODE_ASYNC, /* keyboard mode */
|
||||||
confine_to, /* confine_to = in which window should the cursor stay */
|
confine_to, /* confine_to = in which window should the cursor stay */
|
||||||
xcursor, /* possibly display a special cursor */
|
xcursor, /* possibly display a special cursor */
|
||||||
XCB_CURRENT_TIME);
|
XCB_CURRENT_TIME);
|
||||||
|
|
||||||
if ((reply = xcb_grab_pointer_reply(conn, cookie, &error)) == NULL) {
|
if ((reply = xcb_grab_pointer_reply(conn, cookie, &error)) == NULL) {
|
||||||
ELOG("Could not grab pointer (error_code = %d)\n", error->error_code);
|
ELOG("Could not grab pointer (error_code = %d)\n", error->error_code);
|
||||||
@ -707,12 +707,12 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_
|
|||||||
xcb_grab_keyboard_reply_t *keyb_reply;
|
xcb_grab_keyboard_reply_t *keyb_reply;
|
||||||
|
|
||||||
keyb_cookie = xcb_grab_keyboard(conn,
|
keyb_cookie = xcb_grab_keyboard(conn,
|
||||||
false, /* get all keyboard events */
|
false, /* get all keyboard events */
|
||||||
root, /* grab the root window */
|
root, /* grab the root window */
|
||||||
XCB_CURRENT_TIME,
|
XCB_CURRENT_TIME,
|
||||||
XCB_GRAB_MODE_ASYNC, /* continue processing pointer events as normal */
|
XCB_GRAB_MODE_ASYNC, /* continue processing pointer events as normal */
|
||||||
XCB_GRAB_MODE_ASYNC /* keyboard mode */
|
XCB_GRAB_MODE_ASYNC /* keyboard mode */
|
||||||
);
|
);
|
||||||
|
|
||||||
if ((keyb_reply = xcb_grab_keyboard_reply(conn, keyb_cookie, &error)) == NULL) {
|
if ((keyb_reply = xcb_grab_keyboard_reply(conn, keyb_cookie, &error)) == NULL) {
|
||||||
ELOG("Could not grab keyboard (error_code = %d)\n", error->error_code);
|
ELOG("Could not grab keyboard (error_code = %d)\n", error->error_code);
|
||||||
@ -789,18 +789,16 @@ void floating_fix_coordinates(Con *con, Rect *old_rect, Rect *new_rect) {
|
|||||||
new_rect->x, new_rect->y, new_rect->width, new_rect->height);
|
new_rect->x, new_rect->y, new_rect->width, new_rect->height);
|
||||||
/* First we get the x/y coordinates relative to the x/y coordinates
|
/* First we get the x/y coordinates relative to the x/y coordinates
|
||||||
* of the output on which the window is on */
|
* of the output on which the window is on */
|
||||||
int32_t rel_x = con->rect.x - old_rect->x + (int32_t)(con->rect.width / 2);
|
int32_t rel_x = con->rect.x - old_rect->x + (int32_t)(con->rect.width / 2);
|
||||||
int32_t rel_y = con->rect.y - old_rect->y + (int32_t)(con->rect.height / 2);
|
int32_t rel_y = con->rect.y - old_rect->y + (int32_t)(con->rect.height / 2);
|
||||||
/* Then we calculate a fraction, for example 0.63 for a window
|
/* Then we calculate a fraction, for example 0.63 for a window
|
||||||
* which is at y = 1212 of a 1920 px high output */
|
* which is at y = 1212 of a 1920 px high output */
|
||||||
DLOG("rel_x = %d, rel_y = %d, fraction_x = %f, fraction_y = %f, output->w = %d, output->h = %d\n",
|
DLOG("rel_x = %d, rel_y = %d, fraction_x = %f, fraction_y = %f, output->w = %d, output->h = %d\n",
|
||||||
rel_x, rel_y, (double)rel_x / old_rect->width, (double)rel_y / old_rect->height,
|
rel_x, rel_y, (double)rel_x / old_rect->width, (double)rel_y / old_rect->height,
|
||||||
old_rect->width, old_rect->height);
|
old_rect->width, old_rect->height);
|
||||||
/* Here we have to multiply at first. Or we will lose precision when not compiled with -msse2 */
|
/* Here we have to multiply at first. Or we will lose precision when not compiled with -msse2 */
|
||||||
con->rect.x = (int32_t)new_rect->x + (double)(rel_x * (int32_t)new_rect->width)
|
con->rect.x = (int32_t)new_rect->x + (double)(rel_x * (int32_t)new_rect->width) / (int32_t)old_rect->width - (int32_t)(con->rect.width / 2);
|
||||||
/ (int32_t)old_rect->width - (int32_t)(con->rect.width / 2);
|
con->rect.y = (int32_t)new_rect->y + (double)(rel_y * (int32_t)new_rect->height) / (int32_t)old_rect->height - (int32_t)(con->rect.height / 2);
|
||||||
con->rect.y = (int32_t)new_rect->y + (double)(rel_y * (int32_t)new_rect->height)
|
|
||||||
/ (int32_t)old_rect->height - (int32_t)(con->rect.height / 2);
|
|
||||||
DLOG("Resulting coordinates: x = %d, y = %d\n", con->rect.x, con->rect.y);
|
DLOG("Resulting coordinates: x = %d, y = %d\n", con->rect.x, con->rect.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
src/handlers.c
110
src/handlers.c
@ -58,10 +58,11 @@ bool event_is_ignored(const int sequence, const int response_type) {
|
|||||||
event = SLIST_NEXT(event, ignore_events);
|
event = SLIST_NEXT(event, ignore_events);
|
||||||
SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events);
|
SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events);
|
||||||
free(save);
|
free(save);
|
||||||
} else event = SLIST_NEXT(event, ignore_events);
|
} else
|
||||||
|
event = SLIST_NEXT(event, ignore_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLIST_FOREACH(event, &ignore_events, ignore_events) {
|
SLIST_FOREACH (event, &ignore_events, ignore_events) {
|
||||||
if (event->sequence != sequence)
|
if (event->sequence != sequence)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) {
|
|||||||
layout_t layout = (enter_child ? con->parent->layout : con->layout);
|
layout_t layout = (enter_child ? con->parent->layout : con->layout);
|
||||||
if (layout == L_DEFAULT) {
|
if (layout == L_DEFAULT) {
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
if (rect_contains(child->deco_rect, event->event_x, event->event_y)) {
|
if (rect_contains(child->deco_rect, event->event_x, event->event_y)) {
|
||||||
LOG("using child %p / %s instead!\n", child, child->name);
|
LOG("using child %p / %s instead!\n", child, child->name);
|
||||||
con = child;
|
con = child;
|
||||||
@ -208,7 +209,6 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_motion_notify(xcb_motion_notify_event_t *event) {
|
static void handle_motion_notify(xcb_motion_notify_event_t *event) {
|
||||||
|
|
||||||
last_timestamp = event->time;
|
last_timestamp = event->time;
|
||||||
|
|
||||||
/* Skip events where the pointer was over a child window, we are only
|
/* Skip events where the pointer was over a child window, we are only
|
||||||
@ -231,7 +231,7 @@ static void handle_motion_notify(xcb_motion_notify_event_t *event) {
|
|||||||
|
|
||||||
/* see over which rect the user is */
|
/* see over which rect the user is */
|
||||||
Con *current;
|
Con *current;
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
|
||||||
if (!rect_contains(current->deco_rect, event->event_x, event->event_y))
|
if (!rect_contains(current->deco_rect, event->event_x, event->event_y))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
|
|||||||
Con *con;
|
Con *con;
|
||||||
|
|
||||||
DLOG("window 0x%08x wants to be at %dx%d with %dx%d\n",
|
DLOG("window 0x%08x wants to be at %dx%d with %dx%d\n",
|
||||||
event->window, event->x, event->y, event->width, event->height);
|
event->window, event->x, event->y, event->width, event->height);
|
||||||
|
|
||||||
/* For unmanaged windows, we just execute the configure request. As soon as
|
/* For unmanaged windows, we just execute the configure request. As soon as
|
||||||
* it gets mapped, we will take over anyways. */
|
* it gets mapped, we will take over anyways. */
|
||||||
@ -308,12 +308,13 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
|
|||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
uint32_t values[7];
|
uint32_t values[7];
|
||||||
int c = 0;
|
int c = 0;
|
||||||
#define COPY_MASK_MEMBER(mask_member, event_member) do { \
|
#define COPY_MASK_MEMBER(mask_member, event_member) \
|
||||||
if (event->value_mask & mask_member) { \
|
do { \
|
||||||
mask |= mask_member; \
|
if (event->value_mask & mask_member) { \
|
||||||
values[c++] = event->event_member; \
|
mask |= mask_member; \
|
||||||
} \
|
values[c++] = event->event_member; \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_X, x);
|
COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_X, x);
|
||||||
COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_Y, y);
|
COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_Y, y);
|
||||||
@ -548,7 +549,7 @@ static bool window_name_changed(i3Window *window, char *old_name) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
|
static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
|
||||||
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
|
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
|
||||||
Con *con;
|
Con *con;
|
||||||
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
||||||
return false;
|
return false;
|
||||||
@ -573,7 +574,7 @@ static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state,
|
static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state,
|
||||||
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
|
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
|
||||||
Con *con;
|
Con *con;
|
||||||
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
||||||
return false;
|
return false;
|
||||||
@ -657,7 +658,7 @@ static void handle_expose_event(xcb_expose_event_t *event) {
|
|||||||
static void handle_client_message(xcb_client_message_event_t *event) {
|
static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
/* If this is a startup notification ClientMessage, the library will handle
|
/* If this is a startup notification ClientMessage, the library will handle
|
||||||
* it and call our monitor_event() callback. */
|
* it and call our monitor_event() callback. */
|
||||||
if (sn_xcb_display_process_event(sndisplay, (xcb_generic_event_t*)event))
|
if (sn_xcb_display_process_event(sndisplay, (xcb_generic_event_t *)event))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG("ClientMessage for window 0x%08x\n", event->window);
|
LOG("ClientMessage for window 0x%08x\n", event->window);
|
||||||
@ -757,7 +758,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
|
|||||||
ev->data.data32[0] = window;
|
ev->data.data32[0] = window;
|
||||||
ev->data.data32[1] = rnd;
|
ev->data.data32[1] = rnd;
|
||||||
|
|
||||||
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char*)ev);
|
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)ev);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
free(reply);
|
free(reply);
|
||||||
} else if (event->type == A__NET_REQUEST_FRAME_EXTENTS) {
|
} else if (event->type == A__NET_REQUEST_FRAME_EXTENTS) {
|
||||||
@ -779,16 +780,16 @@ static void handle_client_message(xcb_client_message_event_t *event) {
|
|||||||
Rect r = {
|
Rect r = {
|
||||||
config.default_border_width, /* left */
|
config.default_border_width, /* left */
|
||||||
config.default_border_width, /* right */
|
config.default_border_width, /* right */
|
||||||
config.font.height + 5, /* top */
|
config.font.height + 5, /* top */
|
||||||
config.default_border_width /* bottom */
|
config.default_border_width /* bottom */
|
||||||
};
|
};
|
||||||
xcb_change_property(
|
xcb_change_property(
|
||||||
conn,
|
conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
event->window,
|
event->window,
|
||||||
A__NET_FRAME_EXTENTS,
|
A__NET_FRAME_EXTENTS,
|
||||||
XCB_ATOM_CARDINAL, 32, 4,
|
XCB_ATOM_CARDINAL, 32, 4,
|
||||||
&r);
|
&r);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
} else {
|
} else {
|
||||||
DLOG("unhandled clientmessage\n");
|
DLOG("unhandled clientmessage\n");
|
||||||
@ -814,7 +815,7 @@ int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_wi
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
||||||
xcb_atom_t name, xcb_get_property_reply_t *reply) {
|
xcb_atom_t name, xcb_get_property_reply_t *reply) {
|
||||||
Con *con = con_by_window_id(window);
|
Con *con = con_by_window_id(window);
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
DLOG("Received WM_NORMAL_HINTS for unknown client\n");
|
DLOG("Received WM_NORMAL_HINTS for unknown client\n");
|
||||||
@ -823,7 +824,7 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
|||||||
|
|
||||||
xcb_size_hints_t size_hints;
|
xcb_size_hints_t size_hints;
|
||||||
|
|
||||||
//CLIENT_LOG(client);
|
//CLIENT_LOG(client);
|
||||||
|
|
||||||
/* If the hints were already in this event, use them, if not, request them */
|
/* If the hints were already in this event, use them, if not, request them */
|
||||||
if (reply != NULL)
|
if (reply != NULL)
|
||||||
@ -903,7 +904,8 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
|||||||
aspect_ratio = min_aspect;
|
aspect_ratio = min_aspect;
|
||||||
} else if ((width / height) > max_aspect) {
|
} else if ((width / height) > max_aspect) {
|
||||||
aspect_ratio = max_aspect;
|
aspect_ratio = max_aspect;
|
||||||
} else goto render_and_return;
|
} else
|
||||||
|
goto render_and_return;
|
||||||
|
|
||||||
if (fabs(con->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
|
if (fabs(con->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
|
||||||
con->aspect_ratio = aspect_ratio;
|
con->aspect_ratio = aspect_ratio;
|
||||||
@ -922,7 +924,7 @@ render_and_return:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
||||||
xcb_atom_t name, xcb_get_property_reply_t *reply) {
|
xcb_atom_t name, xcb_get_property_reply_t *reply) {
|
||||||
Con *con = con_by_window_id(window);
|
Con *con = con_by_window_id(window);
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
DLOG("Received WM_HINTS for unknown client\n");
|
DLOG("Received WM_HINTS for unknown client\n");
|
||||||
@ -947,7 +949,7 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
||||||
xcb_atom_t name, xcb_get_property_reply_t *prop) {
|
xcb_atom_t name, xcb_get_property_reply_t *prop) {
|
||||||
Con *con;
|
Con *con;
|
||||||
|
|
||||||
if ((con = con_by_window_id(window)) == NULL || con->window == NULL) {
|
if ((con = con_by_window_id(window)) == NULL || con->window == NULL) {
|
||||||
@ -957,7 +959,8 @@ static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t sta
|
|||||||
|
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
||||||
false, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 32), NULL);
|
false, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 32),
|
||||||
|
NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -973,14 +976,15 @@ static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t sta
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
static bool handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
|
||||||
xcb_atom_t name, xcb_get_property_reply_t *prop) {
|
xcb_atom_t name, xcb_get_property_reply_t *prop) {
|
||||||
Con *con;
|
Con *con;
|
||||||
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
||||||
false, window, A_WM_CLIENT_LEADER, XCB_ATOM_WINDOW, 0, 32), NULL);
|
false, window, A_WM_CLIENT_LEADER, XCB_ATOM_WINDOW, 0, 32),
|
||||||
|
NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1052,14 +1056,13 @@ struct property_handler_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct property_handler_t property_handlers[] = {
|
static struct property_handler_t property_handlers[] = {
|
||||||
{ 0, 128, handle_windowname_change },
|
{0, 128, handle_windowname_change},
|
||||||
{ 0, UINT_MAX, handle_hints },
|
{0, UINT_MAX, handle_hints},
|
||||||
{ 0, 128, handle_windowname_change_legacy },
|
{0, 128, handle_windowname_change_legacy},
|
||||||
{ 0, UINT_MAX, handle_normal_hints },
|
{0, UINT_MAX, handle_normal_hints},
|
||||||
{ 0, UINT_MAX, handle_clientleader_change },
|
{0, UINT_MAX, handle_clientleader_change},
|
||||||
{ 0, UINT_MAX, handle_transient_for },
|
{0, UINT_MAX, handle_transient_for},
|
||||||
{ 0, 128, handle_windowrole_change }
|
{0, 128, handle_windowrole_change}};
|
||||||
};
|
|
||||||
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
|
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1068,7 +1071,6 @@ static struct property_handler_t property_handlers[] = {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void property_handlers_init(void) {
|
void property_handlers_init(void) {
|
||||||
|
|
||||||
sn_monitor_context_new(sndisplay, conn_screen, startup_monitor_event, NULL, NULL);
|
sn_monitor_context_new(sndisplay, conn_screen, startup_monitor_event, NULL, NULL);
|
||||||
|
|
||||||
property_handlers[0].atom = A__NET_WM_NAME;
|
property_handlers[0].atom = A__NET_WM_NAME;
|
||||||
@ -1122,61 +1124,61 @@ void handle_event(int type, xcb_generic_event_t *event) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
case XCB_KEY_RELEASE:
|
case XCB_KEY_RELEASE:
|
||||||
handle_key_press((xcb_key_press_event_t*)event);
|
handle_key_press((xcb_key_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
handle_button_press((xcb_button_press_event_t*)event);
|
handle_button_press((xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_MAP_REQUEST:
|
case XCB_MAP_REQUEST:
|
||||||
handle_map_request((xcb_map_request_event_t*)event);
|
handle_map_request((xcb_map_request_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_UNMAP_NOTIFY:
|
case XCB_UNMAP_NOTIFY:
|
||||||
handle_unmap_notify_event((xcb_unmap_notify_event_t*)event);
|
handle_unmap_notify_event((xcb_unmap_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY:
|
||||||
handle_destroy_notify_event((xcb_destroy_notify_event_t*)event);
|
handle_destroy_notify_event((xcb_destroy_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
handle_expose_event((xcb_expose_event_t*)event);
|
handle_expose_event((xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_MOTION_NOTIFY:
|
case XCB_MOTION_NOTIFY:
|
||||||
handle_motion_notify((xcb_motion_notify_event_t*)event);
|
handle_motion_notify((xcb_motion_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Enter window = user moved his mouse over the window */
|
/* Enter window = user moved his mouse over the window */
|
||||||
case XCB_ENTER_NOTIFY:
|
case XCB_ENTER_NOTIFY:
|
||||||
handle_enter_notify((xcb_enter_notify_event_t*)event);
|
handle_enter_notify((xcb_enter_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Client message are sent to the root window. The only interesting
|
/* Client message are sent to the root window. The only interesting
|
||||||
* client message for us is _NET_WM_STATE, we honour
|
* client message for us is _NET_WM_STATE, we honour
|
||||||
* _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION */
|
* _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION */
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
handle_client_message((xcb_client_message_event_t*)event);
|
handle_client_message((xcb_client_message_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Configure request = window tried to change size on its own */
|
/* Configure request = window tried to change size on its own */
|
||||||
case XCB_CONFIGURE_REQUEST:
|
case XCB_CONFIGURE_REQUEST:
|
||||||
handle_configure_request((xcb_configure_request_event_t*)event);
|
handle_configure_request((xcb_configure_request_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
|
/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
|
||||||
case XCB_MAPPING_NOTIFY:
|
case XCB_MAPPING_NOTIFY:
|
||||||
handle_mapping_notify((xcb_mapping_notify_event_t*)event);
|
handle_mapping_notify((xcb_mapping_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_FOCUS_IN:
|
case XCB_FOCUS_IN:
|
||||||
handle_focus_in((xcb_focus_in_event_t*)event);
|
handle_focus_in((xcb_focus_in_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_PROPERTY_NOTIFY: {
|
case XCB_PROPERTY_NOTIFY: {
|
||||||
xcb_property_notify_event_t *e = (xcb_property_notify_event_t*)event;
|
xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)event;
|
||||||
last_timestamp = e->time;
|
last_timestamp = e->time;
|
||||||
property_notify(e->state, e->window, e->atom);
|
property_notify(e->state, e->window, e->atom);
|
||||||
break;
|
break;
|
||||||
|
130
src/ipc.c
130
src/ipc.c
@ -50,8 +50,8 @@ static bool mkdirp(const char *path) {
|
|||||||
}
|
}
|
||||||
char *copy = sstrdup(path);
|
char *copy = sstrdup(path);
|
||||||
/* strip trailing slashes, if any */
|
/* strip trailing slashes, if any */
|
||||||
while (copy[strlen(copy)-1] == '/')
|
while (copy[strlen(copy) - 1] == '/')
|
||||||
copy[strlen(copy)-1] = '\0';
|
copy[strlen(copy) - 1] = '\0';
|
||||||
|
|
||||||
char *sep = strrchr(copy, '/');
|
char *sep = strrchr(copy, '/');
|
||||||
if (sep == NULL) {
|
if (sep == NULL) {
|
||||||
@ -74,7 +74,7 @@ static bool mkdirp(const char *path) {
|
|||||||
*/
|
*/
|
||||||
void ipc_send_event(const char *event, uint32_t message_type, const char *payload) {
|
void ipc_send_event(const char *event, uint32_t message_type, const char *payload) {
|
||||||
ipc_client *current;
|
ipc_client *current;
|
||||||
TAILQ_FOREACH(current, &all_clients, clients) {
|
TAILQ_FOREACH (current, &all_clients, clients) {
|
||||||
/* see if this client is interested in this event */
|
/* see if this client is interested in this event */
|
||||||
bool interested = false;
|
bool interested = false;
|
||||||
for (int i = 0; i < current->num_events; i++) {
|
for (int i = 0; i < current->num_events; i++) {
|
||||||
@ -86,7 +86,7 @@ void ipc_send_event(const char *event, uint32_t message_type, const char *payloa
|
|||||||
if (!interested)
|
if (!interested)
|
||||||
continue;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +115,11 @@ IPC_HANDLER(command) {
|
|||||||
/* To get a properly terminated buffer, we copy
|
/* To get a properly terminated buffer, we copy
|
||||||
* message_size bytes out of the buffer */
|
* message_size bytes out of the buffer */
|
||||||
char *command = scalloc(message_size + 1);
|
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);
|
LOG("IPC: received: *%s*\n", command);
|
||||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||||
|
|
||||||
CommandResult *result = parse_command((const char*)command, gen);
|
CommandResult *result = parse_command((const char *)command, gen);
|
||||||
free(command);
|
free(command);
|
||||||
|
|
||||||
if (result->needs_tree_render)
|
if (result->needs_tree_render)
|
||||||
@ -132,7 +132,7 @@ IPC_HANDLER(command) {
|
|||||||
yajl_gen_get_buf(gen, &reply, &length);
|
yajl_gen_get_buf(gen, &reply, &length);
|
||||||
|
|
||||||
ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_COMMAND,
|
ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_COMMAND,
|
||||||
(const uint8_t*)reply);
|
(const uint8_t *)reply);
|
||||||
|
|
||||||
yajl_gen_free(gen);
|
yajl_gen_free(gen);
|
||||||
}
|
}
|
||||||
@ -189,7 +189,8 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
else {
|
else {
|
||||||
if (con_orientation(con) == HORIZ)
|
if (con_orientation(con) == HORIZ)
|
||||||
ystr("horizontal");
|
ystr("horizontal");
|
||||||
else ystr("vertical");
|
else
|
||||||
|
ystr("vertical");
|
||||||
}
|
}
|
||||||
|
|
||||||
ystr("scratchpad_state");
|
ystr("scratchpad_state");
|
||||||
@ -208,7 +209,8 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
ystr("percent");
|
ystr("percent");
|
||||||
if (con->percent == 0.0)
|
if (con->percent == 0.0)
|
||||||
y(null);
|
y(null);
|
||||||
else y(double, con->percent);
|
else
|
||||||
|
y(double, con->percent);
|
||||||
|
|
||||||
ystr("urgent");
|
ystr("urgent");
|
||||||
y(bool, con->urgent);
|
y(bool, con->urgent);
|
||||||
@ -308,7 +310,8 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
ystr("window");
|
ystr("window");
|
||||||
if (con->window)
|
if (con->window)
|
||||||
y(integer, con->window->id);
|
y(integer, con->window->id);
|
||||||
else y(null);
|
else
|
||||||
|
y(null);
|
||||||
|
|
||||||
if (con->window && !inplace_restart) {
|
if (con->window && !inplace_restart) {
|
||||||
/* Window properties are useless to preserve when restarting because
|
/* Window properties are useless to preserve when restarting because
|
||||||
@ -317,12 +320,13 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
ystr("window_properties");
|
ystr("window_properties");
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
#define DUMP_PROPERTY(key, prop_name) do { \
|
#define DUMP_PROPERTY(key, prop_name) \
|
||||||
if (con->window->prop_name != NULL) { \
|
do { \
|
||||||
ystr(key); \
|
if (con->window->prop_name != NULL) { \
|
||||||
ystr(con->window->prop_name); \
|
ystr(key); \
|
||||||
} \
|
ystr(con->window->prop_name); \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
DUMP_PROPERTY("class", class_class);
|
DUMP_PROPERTY("class", class_class);
|
||||||
DUMP_PROPERTY("instance", class_instance);
|
DUMP_PROPERTY("instance", class_instance);
|
||||||
@ -340,7 +344,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
y(array_open);
|
y(array_open);
|
||||||
Con *node;
|
Con *node;
|
||||||
if (con->type != CT_DOCKAREA || !inplace_restart) {
|
if (con->type != CT_DOCKAREA || !inplace_restart) {
|
||||||
TAILQ_FOREACH(node, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (node, &(con->nodes_head), nodes) {
|
||||||
dump_node(gen, node, inplace_restart);
|
dump_node(gen, node, inplace_restart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,14 +352,14 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
|
|
||||||
ystr("floating_nodes");
|
ystr("floating_nodes");
|
||||||
y(array_open);
|
y(array_open);
|
||||||
TAILQ_FOREACH(node, &(con->floating_head), floating_windows) {
|
TAILQ_FOREACH (node, &(con->floating_head), floating_windows) {
|
||||||
dump_node(gen, node, inplace_restart);
|
dump_node(gen, node, inplace_restart);
|
||||||
}
|
}
|
||||||
y(array_close);
|
y(array_close);
|
||||||
|
|
||||||
ystr("focus");
|
ystr("focus");
|
||||||
y(array_open);
|
y(array_open);
|
||||||
TAILQ_FOREACH(node, &(con->focus_head), focused) {
|
TAILQ_FOREACH (node, &(con->focus_head), focused) {
|
||||||
y(integer, (long int)node);
|
y(integer, (long int)node);
|
||||||
}
|
}
|
||||||
y(array_close);
|
y(array_close);
|
||||||
@ -382,7 +386,7 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
ystr("swallows");
|
ystr("swallows");
|
||||||
y(array_open);
|
y(array_open);
|
||||||
Match *match;
|
Match *match;
|
||||||
TAILQ_FOREACH(match, &(con->swallow_head), matches) {
|
TAILQ_FOREACH (match, &(con->swallow_head), matches) {
|
||||||
y(map_open);
|
y(map_open);
|
||||||
if (match->dock != -1) {
|
if (match->dock != -1) {
|
||||||
ystr("dock");
|
ystr("dock");
|
||||||
@ -391,12 +395,13 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
y(integer, match->insert_where);
|
y(integer, match->insert_where);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DUMP_REGEX(re_name) do { \
|
#define DUMP_REGEX(re_name) \
|
||||||
if (match->re_name != NULL) { \
|
do { \
|
||||||
ystr(# re_name); \
|
if (match->re_name != NULL) { \
|
||||||
ystr(match->re_name->pattern); \
|
ystr(#re_name); \
|
||||||
} \
|
ystr(match->re_name->pattern); \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
DUMP_REGEX(class);
|
DUMP_REGEX(class);
|
||||||
DUMP_REGEX(instance);
|
DUMP_REGEX(instance);
|
||||||
@ -441,12 +446,12 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
|||||||
y(array_close);
|
y(array_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define YSTR_IF_SET(name) \
|
#define YSTR_IF_SET(name) \
|
||||||
do { \
|
do { \
|
||||||
if (config->name) { \
|
if (config->name) { \
|
||||||
ystr( # name); \
|
ystr(#name); \
|
||||||
ystr(config->name); \
|
ystr(config->name); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
YSTR_IF_SET(tray_output);
|
YSTR_IF_SET(tray_output);
|
||||||
@ -494,7 +499,7 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
|||||||
case M_MOD3:
|
case M_MOD3:
|
||||||
ystr("Mod3");
|
ystr("Mod3");
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
case M_MOD4:
|
case M_MOD4:
|
||||||
ystr("Mod4");
|
ystr("Mod4");
|
||||||
break;
|
break;
|
||||||
@ -510,7 +515,8 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
|||||||
ystr("position");
|
ystr("position");
|
||||||
if (config->position == P_BOTTOM)
|
if (config->position == P_BOTTOM)
|
||||||
ystr("bottom");
|
ystr("bottom");
|
||||||
else ystr("top");
|
else
|
||||||
|
ystr("top");
|
||||||
|
|
||||||
YSTR_IF_SET(status_command);
|
YSTR_IF_SET(status_command);
|
||||||
YSTR_IF_SET(font);
|
YSTR_IF_SET(font);
|
||||||
@ -528,12 +534,12 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
|||||||
y(bool, config->verbose);
|
y(bool, config->verbose);
|
||||||
|
|
||||||
#undef YSTR_IF_SET
|
#undef YSTR_IF_SET
|
||||||
#define YSTR_IF_SET(name) \
|
#define YSTR_IF_SET(name) \
|
||||||
do { \
|
do { \
|
||||||
if (config->colors.name) { \
|
if (config->colors.name) { \
|
||||||
ystr( # name); \
|
ystr(#name); \
|
||||||
ystr(config->colors.name); \
|
ystr(config->colors.name); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
ystr("colors");
|
ystr("colors");
|
||||||
@ -573,7 +579,6 @@ IPC_HANDLER(tree) {
|
|||||||
y(free);
|
y(free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Formats the reply message for a GET_WORKSPACES request and sends it to the
|
* Formats the reply message for a GET_WORKSPACES request and sends it to the
|
||||||
* client
|
* client
|
||||||
@ -586,18 +591,19 @@ IPC_HANDLER(get_workspaces) {
|
|||||||
Con *focused_ws = con_get_workspace(focused);
|
Con *focused_ws = con_get_workspace(focused);
|
||||||
|
|
||||||
Con *output;
|
Con *output;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
Con *ws;
|
Con *ws;
|
||||||
TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
|
TAILQ_FOREACH (ws, &(output_get_content(output)->nodes_head), nodes) {
|
||||||
assert(ws->type == CT_WORKSPACE);
|
assert(ws->type == CT_WORKSPACE);
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
ystr("num");
|
ystr("num");
|
||||||
if (ws->num == -1)
|
if (ws->num == -1)
|
||||||
y(null);
|
y(null);
|
||||||
else y(integer, ws->num);
|
else
|
||||||
|
y(integer, ws->num);
|
||||||
|
|
||||||
ystr("name");
|
ystr("name");
|
||||||
ystr(ws->name);
|
ystr(ws->name);
|
||||||
@ -650,7 +656,7 @@ IPC_HANDLER(get_outputs) {
|
|||||||
y(array_open);
|
y(array_open);
|
||||||
|
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
ystr("name");
|
ystr("name");
|
||||||
@ -678,7 +684,8 @@ IPC_HANDLER(get_outputs) {
|
|||||||
Con *ws = NULL;
|
Con *ws = NULL;
|
||||||
if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT)))
|
if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT)))
|
||||||
ystr(ws->name);
|
ystr(ws->name);
|
||||||
else y(null);
|
else
|
||||||
|
y(null);
|
||||||
|
|
||||||
y(map_close);
|
y(map_close);
|
||||||
}
|
}
|
||||||
@ -703,7 +710,7 @@ IPC_HANDLER(get_marks) {
|
|||||||
y(array_open);
|
y(array_open);
|
||||||
|
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons)
|
TAILQ_FOREACH (con, &all_cons, all_cons)
|
||||||
if (con->mark != NULL)
|
if (con->mark != NULL)
|
||||||
ystr(con->mark);
|
ystr(con->mark);
|
||||||
|
|
||||||
@ -759,7 +766,7 @@ IPC_HANDLER(get_bar_config) {
|
|||||||
if (message_size == 0) {
|
if (message_size == 0) {
|
||||||
y(array_open);
|
y(array_open);
|
||||||
Barconfig *current;
|
Barconfig *current;
|
||||||
TAILQ_FOREACH(current, &barconfigs, configs) {
|
TAILQ_FOREACH (current, &barconfigs, configs) {
|
||||||
ystr(current->id);
|
ystr(current->id);
|
||||||
}
|
}
|
||||||
y(array_close);
|
y(array_close);
|
||||||
@ -776,10 +783,10 @@ IPC_HANDLER(get_bar_config) {
|
|||||||
/* To get a properly terminated buffer, we copy
|
/* To get a properly terminated buffer, we copy
|
||||||
* message_size bytes out of the buffer */
|
* message_size bytes out of the buffer */
|
||||||
char *bar_id = scalloc(message_size + 1);
|
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);
|
LOG("IPC: looking for config for bar ID \"%s\"\n", bar_id);
|
||||||
Barconfig *current, *config = NULL;
|
Barconfig *current, *config = NULL;
|
||||||
TAILQ_FOREACH(current, &barconfigs, configs) {
|
TAILQ_FOREACH (current, &barconfigs, configs) {
|
||||||
if (strcmp(current->id, bar_id) != 0)
|
if (strcmp(current->id, bar_id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -820,10 +827,10 @@ static int add_subscription(void *extra, const unsigned char *s,
|
|||||||
int event = client->num_events;
|
int event = client->num_events;
|
||||||
|
|
||||||
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()
|
/* We copy the string because it is not null-terminated and strndup()
|
||||||
* is missing on some BSD systems */
|
* is missing on some BSD systems */
|
||||||
client->events[event] = scalloc(len+1);
|
client->events[event] = scalloc(len + 1);
|
||||||
memcpy(client->events[event], s, len);
|
memcpy(client->events[event], s, len);
|
||||||
|
|
||||||
DLOG("client is now subscribed to:\n");
|
DLOG("client is now subscribed to:\n");
|
||||||
@ -845,7 +852,7 @@ IPC_HANDLER(subscribe) {
|
|||||||
ipc_client *current, *client = NULL;
|
ipc_client *current, *client = NULL;
|
||||||
|
|
||||||
/* Search the ipc_client structure for this connection */
|
/* Search the ipc_client structure for this connection */
|
||||||
TAILQ_FOREACH(current, &all_clients, clients) {
|
TAILQ_FOREACH (current, &all_clients, clients) {
|
||||||
if (current->fd != fd)
|
if (current->fd != fd)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -863,23 +870,23 @@ IPC_HANDLER(subscribe) {
|
|||||||
.yajl_string = add_subscription,
|
.yajl_string = add_subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
p = yalloc(&callbacks, (void*)client);
|
p = yalloc(&callbacks, (void *)client);
|
||||||
stat = yajl_parse(p, (const unsigned char*)message, message_size);
|
stat = yajl_parse(p, (const unsigned char *)message, message_size);
|
||||||
if (stat != yajl_status_ok) {
|
if (stat != yajl_status_ok) {
|
||||||
unsigned char *err;
|
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);
|
message_size);
|
||||||
ELOG("YAJL parse error: %s\n", err);
|
ELOG("YAJL parse error: %s\n", err);
|
||||||
yajl_free_error(p, err);
|
yajl_free_error(p, err);
|
||||||
|
|
||||||
const char *reply = "{\"success\":false}";
|
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);
|
yajl_free(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yajl_free(p);
|
yajl_free(p);
|
||||||
const char *reply = "{\"success\":true}";
|
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
|
/* The index of each callback function corresponds to the numeric
|
||||||
@ -925,7 +932,7 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) {
|
|||||||
|
|
||||||
/* Delete the client from the list of clients */
|
/* Delete the client from the list of clients */
|
||||||
ipc_client *current;
|
ipc_client *current;
|
||||||
TAILQ_FOREACH(current, &all_clients, clients) {
|
TAILQ_FOREACH (current, &all_clients, clients) {
|
||||||
if (current->fd != w->fd)
|
if (current->fd != w->fd)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -967,10 +974,11 @@ void ipc_new_client(EV_P_ struct ev_io *w, int revents) {
|
|||||||
struct sockaddr_un peer;
|
struct sockaddr_un peer;
|
||||||
socklen_t len = sizeof(struct sockaddr_un);
|
socklen_t len = sizeof(struct sockaddr_un);
|
||||||
int client;
|
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)
|
if (errno == EINTR)
|
||||||
return;
|
return;
|
||||||
else perror("accept()");
|
else
|
||||||
|
perror("accept()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1024,7 +1032,7 @@ int ipc_create_socket(const char *filename) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, resolved, sizeof(addr.sun_path) - 1);
|
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()");
|
perror("bind()");
|
||||||
free(resolved);
|
free(resolved);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1082,7 +1090,7 @@ void ipc_send_workspace_focus_event(Con *current, Con *old) {
|
|||||||
*/
|
*/
|
||||||
void ipc_send_window_event(const char *property, Con *con) {
|
void ipc_send_window_event(const char *property, Con *con) {
|
||||||
DLOG("Issue IPC window %s event (con = %p, window = 0x%08x)\n",
|
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");
|
setlocale(LC_NUMERIC, "C");
|
||||||
yajl_gen gen = ygenalloc();
|
yajl_gen gen = ygenalloc();
|
||||||
|
@ -37,7 +37,7 @@ struct focus_mapping {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
|
static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
|
||||||
TAILQ_HEAD_INITIALIZER(focus_mappings);
|
TAILQ_HEAD_INITIALIZER(focus_mappings);
|
||||||
|
|
||||||
static int json_start_map(void *ctx) {
|
static int json_start_map(void *ctx) {
|
||||||
LOG("start of map, last_key = %s\n", last_key);
|
LOG("start of map, last_key = %s\n", last_key);
|
||||||
@ -110,10 +110,10 @@ static int json_end_array(void *ctx) {
|
|||||||
if (parsing_focus) {
|
if (parsing_focus) {
|
||||||
/* Clear the list of focus mappings */
|
/* Clear the list of focus mappings */
|
||||||
struct focus_mapping *mapping;
|
struct focus_mapping *mapping;
|
||||||
TAILQ_FOREACH_REVERSE(mapping, &focus_mappings, focus_mappings_head, focus_mappings) {
|
TAILQ_FOREACH_REVERSE (mapping, &focus_mappings, focus_mappings_head, focus_mappings) {
|
||||||
LOG("focus (reverse) %d\n", mapping->old_id);
|
LOG("focus (reverse) %d\n", mapping->old_id);
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &(json_node->focus_head), focused) {
|
TAILQ_FOREACH (con, &(json_node->focus_head), focused) {
|
||||||
if (con->old_id != mapping->old_id)
|
if (con->old_id != mapping->old_id)
|
||||||
continue;
|
continue;
|
||||||
LOG("got it! %p\n", con);
|
LOG("got it! %p\n", con);
|
||||||
@ -136,7 +136,7 @@ static int json_end_array(void *ctx) {
|
|||||||
static int json_key(void *ctx, const unsigned char *val, size_t len) {
|
static int json_key(void *ctx, const unsigned char *val, size_t len) {
|
||||||
LOG("key: %.*s\n", (int)len, val);
|
LOG("key: %.*s\n", (int)len, val);
|
||||||
FREE(last_key);
|
FREE(last_key);
|
||||||
last_key = scalloc((len+1) * sizeof(char));
|
last_key = scalloc((len + 1) * sizeof(char));
|
||||||
memcpy(last_key, val, len);
|
memcpy(last_key, val, len);
|
||||||
if (strcasecmp(last_key, "swallows") == 0)
|
if (strcasecmp(last_key, "swallows") == 0)
|
||||||
parsing_swallows = true;
|
parsing_swallows = true;
|
||||||
@ -175,10 +175,10 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
free(sval);
|
free(sval);
|
||||||
} else {
|
} else {
|
||||||
if (strcasecmp(last_key, "name") == 0) {
|
if (strcasecmp(last_key, "name") == 0) {
|
||||||
json_node->name = scalloc((len+1) * sizeof(char));
|
json_node->name = scalloc((len + 1) * sizeof(char));
|
||||||
memcpy(json_node->name, val, len);
|
memcpy(json_node->name, val, len);
|
||||||
} else if (strcasecmp(last_key, "sticky_group") == 0) {
|
} else if (strcasecmp(last_key, "sticky_group") == 0) {
|
||||||
json_node->sticky_group = scalloc((len+1) * sizeof(char));
|
json_node->sticky_group = scalloc((len + 1) * sizeof(char));
|
||||||
memcpy(json_node->sticky_group, val, len);
|
memcpy(json_node->sticky_group, val, len);
|
||||||
LOG("sticky_group of this container is %s\n", json_node->sticky_group);
|
LOG("sticky_group of this container is %s\n", json_node->sticky_group);
|
||||||
} else if (strcasecmp(last_key, "orientation") == 0) {
|
} else if (strcasecmp(last_key, "orientation") == 0) {
|
||||||
@ -195,7 +195,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->last_split_layout = L_SPLITH;
|
json_node->last_split_layout = L_SPLITH;
|
||||||
else if (strcasecmp(buf, "vertical") == 0)
|
else if (strcasecmp(buf, "vertical") == 0)
|
||||||
json_node->last_split_layout = L_SPLITV;
|
json_node->last_split_layout = L_SPLITV;
|
||||||
else LOG("Unhandled orientation: %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled orientation: %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "border") == 0) {
|
} else if (strcasecmp(last_key, "border") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -209,7 +210,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->border_style = BS_PIXEL;
|
json_node->border_style = BS_PIXEL;
|
||||||
else if (strcasecmp(buf, "normal") == 0)
|
else if (strcasecmp(buf, "normal") == 0)
|
||||||
json_node->border_style = BS_NORMAL;
|
json_node->border_style = BS_NORMAL;
|
||||||
else LOG("Unhandled \"border\": %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled \"border\": %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "type") == 0) {
|
} else if (strcasecmp(last_key, "type") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -226,7 +228,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->type = CT_WORKSPACE;
|
json_node->type = CT_WORKSPACE;
|
||||||
else if (strcasecmp(buf, "dockarea") == 0)
|
else if (strcasecmp(buf, "dockarea") == 0)
|
||||||
json_node->type = CT_DOCKAREA;
|
json_node->type = CT_DOCKAREA;
|
||||||
else LOG("Unhandled \"type\": %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled \"type\": %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "layout") == 0) {
|
} else if (strcasecmp(last_key, "layout") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -246,7 +249,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->layout = L_SPLITH;
|
json_node->layout = L_SPLITH;
|
||||||
else if (strcasecmp(buf, "splitv") == 0)
|
else if (strcasecmp(buf, "splitv") == 0)
|
||||||
json_node->layout = L_SPLITV;
|
json_node->layout = L_SPLITV;
|
||||||
else LOG("Unhandled \"layout\": %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled \"layout\": %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "workspace_layout") == 0) {
|
} else if (strcasecmp(last_key, "workspace_layout") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -257,7 +261,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->workspace_layout = L_STACKED;
|
json_node->workspace_layout = L_STACKED;
|
||||||
else if (strcasecmp(buf, "tabbed") == 0)
|
else if (strcasecmp(buf, "tabbed") == 0)
|
||||||
json_node->workspace_layout = L_TABBED;
|
json_node->workspace_layout = L_TABBED;
|
||||||
else LOG("Unhandled \"workspace_layout\": %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled \"workspace_layout\": %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "last_split_layout") == 0) {
|
} else if (strcasecmp(last_key, "last_split_layout") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -266,7 +271,8 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
|||||||
json_node->last_split_layout = L_SPLITH;
|
json_node->last_split_layout = L_SPLITH;
|
||||||
else if (strcasecmp(buf, "splitv") == 0)
|
else if (strcasecmp(buf, "splitv") == 0)
|
||||||
json_node->last_split_layout = L_SPLITV;
|
json_node->last_split_layout = L_SPLITV;
|
||||||
else LOG("Unhandled \"last_splitlayout\": %s\n", buf);
|
else
|
||||||
|
LOG("Unhandled \"last_splitlayout\": %s\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (strcasecmp(last_key, "mark") == 0) {
|
} else if (strcasecmp(last_key, "mark") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -332,7 +338,8 @@ static int json_int(void *ctx, long long val) {
|
|||||||
r = &(json_node->rect);
|
r = &(json_node->rect);
|
||||||
else if (parsing_window_rect)
|
else if (parsing_window_rect)
|
||||||
r = &(json_node->window_rect);
|
r = &(json_node->window_rect);
|
||||||
else r = &(json_node->geometry);
|
else
|
||||||
|
r = &(json_node->geometry);
|
||||||
if (strcasecmp(last_key, "x") == 0)
|
if (strcasecmp(last_key, "x") == 0)
|
||||||
r->x = val;
|
r->x = val;
|
||||||
else if (strcasecmp(last_key, "y") == 0)
|
else if (strcasecmp(last_key, "y") == 0)
|
||||||
@ -341,9 +348,10 @@ static int json_int(void *ctx, long long val) {
|
|||||||
r->width = val;
|
r->width = val;
|
||||||
else if (strcasecmp(last_key, "height") == 0)
|
else if (strcasecmp(last_key, "height") == 0)
|
||||||
r->height = val;
|
r->height = val;
|
||||||
else ELOG("WARNING: unknown key %s in rect\n", last_key);
|
else
|
||||||
|
ELOG("WARNING: unknown key %s in rect\n", last_key);
|
||||||
DLOG("rect now: (%d, %d, %d, %d)\n",
|
DLOG("rect now: (%d, %d, %d, %d)\n",
|
||||||
r->x, r->y, r->width, r->height);
|
r->x, r->y, r->width, r->height);
|
||||||
}
|
}
|
||||||
if (parsing_swallows) {
|
if (parsing_swallows) {
|
||||||
if (strcasecmp(last_key, "id") == 0) {
|
if (strcasecmp(last_key, "id") == 0) {
|
||||||
@ -415,7 +423,7 @@ void tree_append_json(Con *con, const char *filename, char **errormsg) {
|
|||||||
.yajl_end_array = json_end_array,
|
.yajl_end_array = json_end_array,
|
||||||
};
|
};
|
||||||
g = yajl_gen_alloc(NULL);
|
g = yajl_gen_alloc(NULL);
|
||||||
hand = yajl_alloc(&callbacks, NULL, (void*)g);
|
hand = yajl_alloc(&callbacks, NULL, (void *)g);
|
||||||
/* Allowing comments allows for more user-friendly layout files. */
|
/* Allowing comments allows for more user-friendly layout files. */
|
||||||
yajl_config(hand, yajl_allow_comments, true);
|
yajl_config(hand, yajl_allow_comments, true);
|
||||||
/* Allow multiple values, i.e. multiple nodes to attach */
|
/* Allow multiple values, i.e. multiple nodes to attach */
|
||||||
@ -429,13 +437,12 @@ void tree_append_json(Con *con, const char *filename, char **errormsg) {
|
|||||||
parsing_geometry = false;
|
parsing_geometry = false;
|
||||||
parsing_focus = false;
|
parsing_focus = false;
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
stat = yajl_parse(hand, (const unsigned char*)buf, n);
|
stat = yajl_parse(hand, (const unsigned char *)buf, n);
|
||||||
if (stat != yajl_status_ok)
|
if (stat != yajl_status_ok) {
|
||||||
{
|
unsigned char *str = yajl_get_error(hand, 1, (const unsigned char *)buf, n);
|
||||||
unsigned char *str = yajl_get_error(hand, 1, (const unsigned char*)buf, n);
|
|
||||||
ELOG("JSON parsing error: %s\n", str);
|
ELOG("JSON parsing error: %s\n", str);
|
||||||
if (errormsg != NULL)
|
if (errormsg != NULL)
|
||||||
*errormsg = sstrdup((const char*)str);
|
*errormsg = sstrdup((const char *)str);
|
||||||
yajl_free_error(hand, str);
|
yajl_free_error(hand, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
88
src/log.c
88
src/log.c
@ -92,11 +92,11 @@ void init_logging(void) {
|
|||||||
/* Start SHM logging if shmlog_size is > 0. shmlog_size is SHMLOG_SIZE by
|
/* Start SHM logging if shmlog_size is > 0. shmlog_size is SHMLOG_SIZE by
|
||||||
* default on development versions, and 0 on release versions. If it is
|
* default on development versions, and 0 on release versions. If it is
|
||||||
* not > 0, the user has turned it off, so let's close the logbuffer. */
|
* not > 0, the user has turned it off, so let's close the logbuffer. */
|
||||||
if (shmlog_size > 0 && logbuffer == NULL)
|
if (shmlog_size > 0 && logbuffer == NULL)
|
||||||
open_logbuffer();
|
open_logbuffer();
|
||||||
else if (shmlog_size <= 0 && logbuffer)
|
else if (shmlog_size <= 0 && logbuffer)
|
||||||
close_logbuffer();
|
close_logbuffer();
|
||||||
atexit(purge_zerobyte_logfile);
|
atexit(purge_zerobyte_logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -104,65 +104,65 @@ void init_logging(void) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void open_logbuffer(void) {
|
void open_logbuffer(void) {
|
||||||
/* Reserve 1% of the RAM for the logfile, but at max 25 MiB.
|
/* Reserve 1% of the RAM for the logfile, but at max 25 MiB.
|
||||||
* For 512 MiB of RAM this will lead to a 5 MiB log buffer.
|
* For 512 MiB of RAM this will lead to a 5 MiB log buffer.
|
||||||
* At the moment (2011-12-10), no testcase leads to an i3 log
|
* At the moment (2011-12-10), no testcase leads to an i3 log
|
||||||
* of more than ~ 600 KiB. */
|
* of more than ~ 600 KiB. */
|
||||||
long long physical_mem_bytes;
|
long long physical_mem_bytes;
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
int mib[2] = { CTL_HW, HW_MEMSIZE };
|
int mib[2] = {CTL_HW, HW_MEMSIZE};
|
||||||
size_t length = sizeof(long long);
|
size_t length = sizeof(long long);
|
||||||
sysctl(mib, 2, &physical_mem_bytes, &length, NULL, 0);
|
sysctl(mib, 2, &physical_mem_bytes, &length, NULL, 0);
|
||||||
#else
|
#else
|
||||||
physical_mem_bytes = (long long)sysconf(_SC_PHYS_PAGES) *
|
physical_mem_bytes = (long long)sysconf(_SC_PHYS_PAGES) *
|
||||||
sysconf(_SC_PAGESIZE);
|
sysconf(_SC_PAGESIZE);
|
||||||
#endif
|
#endif
|
||||||
logbuffer_size = min(physical_mem_bytes * 0.01, shmlog_size);
|
logbuffer_size = min(physical_mem_bytes * 0.01, shmlog_size);
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
sasprintf(&shmlogname, "/tmp/i3-log-%d", getpid());
|
sasprintf(&shmlogname, "/tmp/i3-log-%d", getpid());
|
||||||
#else
|
#else
|
||||||
sasprintf(&shmlogname, "/i3-log-%d", getpid());
|
sasprintf(&shmlogname, "/i3-log-%d", getpid());
|
||||||
#endif
|
#endif
|
||||||
logbuffer_shm = shm_open(shmlogname, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
|
logbuffer_shm = shm_open(shmlogname, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
|
||||||
if (logbuffer_shm == -1) {
|
if (logbuffer_shm == -1) {
|
||||||
fprintf(stderr, "Could not shm_open SHM segment for the i3 log: %s\n", strerror(errno));
|
fprintf(stderr, "Could not shm_open SHM segment for the i3 log: %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||||
if (ftruncate(logbuffer_shm, logbuffer_size) == -1) {
|
if (ftruncate(logbuffer_shm, logbuffer_size) == -1) {
|
||||||
fprintf(stderr, "Could not ftruncate SHM segment for the i3 log: %s\n", strerror(errno));
|
fprintf(stderr, "Could not ftruncate SHM segment for the i3 log: %s\n", strerror(errno));
|
||||||
#else
|
#else
|
||||||
int ret;
|
int ret;
|
||||||
if ((ret = posix_fallocate(logbuffer_shm, 0, logbuffer_size)) != 0) {
|
if ((ret = posix_fallocate(logbuffer_shm, 0, logbuffer_size)) != 0) {
|
||||||
fprintf(stderr, "Could not ftruncate SHM segment for the i3 log: %s\n", strerror(ret));
|
fprintf(stderr, "Could not ftruncate SHM segment for the i3 log: %s\n", strerror(ret));
|
||||||
#endif
|
#endif
|
||||||
close(logbuffer_shm);
|
close(logbuffer_shm);
|
||||||
shm_unlink(shmlogname);
|
shm_unlink(shmlogname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logbuffer = mmap(NULL, logbuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, logbuffer_shm, 0);
|
logbuffer = mmap(NULL, logbuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, logbuffer_shm, 0);
|
||||||
if (logbuffer == MAP_FAILED) {
|
if (logbuffer == MAP_FAILED) {
|
||||||
close_logbuffer();
|
close_logbuffer();
|
||||||
fprintf(stderr, "Could not mmap SHM segment for the i3 log: %s\n", strerror(errno));
|
fprintf(stderr, "Could not mmap SHM segment for the i3 log: %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize with 0-bytes, just to be sure… */
|
/* Initialize with 0-bytes, just to be sure… */
|
||||||
memset(logbuffer, '\0', logbuffer_size);
|
memset(logbuffer, '\0', logbuffer_size);
|
||||||
|
|
||||||
header = (i3_shmlog_header*)logbuffer;
|
header = (i3_shmlog_header *)logbuffer;
|
||||||
|
|
||||||
pthread_condattr_t cond_attr;
|
pthread_condattr_t cond_attr;
|
||||||
pthread_condattr_init(&cond_attr);
|
pthread_condattr_init(&cond_attr);
|
||||||
if (pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED) != 0)
|
if (pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED) != 0)
|
||||||
fprintf(stderr, "pthread_condattr_setpshared() failed, i3-dump-log -f will not work!\n");
|
fprintf(stderr, "pthread_condattr_setpshared() failed, i3-dump-log -f will not work!\n");
|
||||||
pthread_cond_init(&(header->condvar), &cond_attr);
|
pthread_cond_init(&(header->condvar), &cond_attr);
|
||||||
|
|
||||||
logwalk = logbuffer + sizeof(i3_shmlog_header);
|
logwalk = logbuffer + sizeof(i3_shmlog_header);
|
||||||
loglastwrap = logbuffer + logbuffer_size;
|
loglastwrap = logbuffer + logbuffer_size;
|
||||||
store_log_markers();
|
store_log_markers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
88
src/main.c
88
src/main.c
@ -131,7 +131,7 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
if (event_is_ignored(event->sequence, 0))
|
if (event_is_ignored(event->sequence, 0))
|
||||||
DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
|
DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
|
||||||
else {
|
else {
|
||||||
xcb_generic_error_t *error = (xcb_generic_error_t*)event;
|
xcb_generic_error_t *error = (xcb_generic_error_t *)event;
|
||||||
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
||||||
error->sequence, error->error_code);
|
error->sequence, error->error_code);
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ static void xkb_got_event(EV_P_ struct ev_io *w, int revents) {
|
|||||||
* mapping_notify once. */
|
* mapping_notify once. */
|
||||||
bool mapping_changed = false;
|
bool mapping_changed = false;
|
||||||
while (XPending(xkbdpy)) {
|
while (XPending(xkbdpy)) {
|
||||||
XNextEvent(xkbdpy, (XEvent*)&ev);
|
XNextEvent(xkbdpy, (XEvent *)&ev);
|
||||||
/* While we should never receive a non-XKB event,
|
/* While we should never receive a non-XKB event,
|
||||||
* better do sanity checking */
|
* better do sanity checking */
|
||||||
if (ev.type != xkb_event_base)
|
if (ev.type != xkb_event_base)
|
||||||
@ -268,7 +268,7 @@ static void handle_signal(int sig, siginfo_t *info, void *data) {
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
/* Keep a symbol pointing to the I3_VERSION string constant so that we have
|
/* Keep a symbol pointing to the I3_VERSION string constant so that we have
|
||||||
* it in gdb backtraces. */
|
* it in gdb backtraces. */
|
||||||
const char *i3_version __attribute__ ((unused)) = I3_VERSION;
|
const char *i3_version __attribute__((unused)) = I3_VERSION;
|
||||||
char *override_configpath = NULL;
|
char *override_configpath = NULL;
|
||||||
bool autostart = true;
|
bool autostart = true;
|
||||||
char *layout_path = NULL;
|
char *layout_path = NULL;
|
||||||
@ -296,8 +296,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"fake_outputs", required_argument, 0, 0},
|
{"fake_outputs", required_argument, 0, 0},
|
||||||
{"fake-outputs", required_argument, 0, 0},
|
{"fake-outputs", required_argument, 0, 0},
|
||||||
{"force-old-config-parser-v4.4-only", no_argument, 0, 0},
|
{"force-old-config-parser-v4.4-only", no_argument, 0, 0},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
int option_index = 0, opt;
|
int option_index = 0, opt;
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@ -403,7 +402,7 @@ int main(int argc, char *argv[]) {
|
|||||||
ELOG("You are passing --force-old-config-parser-v4.4-only, but that flag was removed by now.\n");
|
ELOG("You are passing --force-old-config-parser-v4.4-only, but that flag was removed by now.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
|
fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
@ -427,7 +426,8 @@ int main(int argc, char *argv[]) {
|
|||||||
fprintf(stderr, "\t--shmlog-size <limit>\n"
|
fprintf(stderr, "\t--shmlog-size <limit>\n"
|
||||||
"\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
|
"\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
|
||||||
"\tto 0 disables SHM logging entirely.\n"
|
"\tto 0 disables SHM logging entirely.\n"
|
||||||
"\tThe default is %d bytes.\n", shmlog_size);
|
"\tThe default is %d bytes.\n",
|
||||||
|
shmlog_size);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
|
fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
|
||||||
"to send to a currently running i3 (like i3-msg). This allows you to\n"
|
"to send to a currently running i3 (like i3-msg). This allows you to\n"
|
||||||
@ -478,11 +478,11 @@ int main(int argc, char *argv[]) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
err(EXIT_FAILURE, "Could not connect to i3");
|
err(EXIT_FAILURE, "Could not connect to i3");
|
||||||
|
|
||||||
if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
|
if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
|
||||||
(uint8_t*)payload) == -1)
|
(uint8_t *)payload) == -1)
|
||||||
err(EXIT_FAILURE, "IPC: write()");
|
err(EXIT_FAILURE, "IPC: write()");
|
||||||
|
|
||||||
uint32_t reply_length;
|
uint32_t reply_length;
|
||||||
@ -505,7 +505,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* Try to enable core dumps by default when running a debug build */
|
/* Try to enable core dumps by default when running a debug build */
|
||||||
if (is_debug_build()) {
|
if (is_debug_build()) {
|
||||||
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
|
struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
|
||||||
setrlimit(RLIMIT_CORE, &limit);
|
setrlimit(RLIMIT_CORE, &limit);
|
||||||
|
|
||||||
/* The following code is helpful, but not required. We thus don’t pay
|
/* The following code is helpful, but not required. We thus don’t pay
|
||||||
@ -544,7 +544,7 @@ int main(int argc, char *argv[]) {
|
|||||||
* for the nagbar when config errors are found. */
|
* for the nagbar when config errors are found. */
|
||||||
main_loop = EV_DEFAULT;
|
main_loop = EV_DEFAULT;
|
||||||
if (main_loop == NULL)
|
if (main_loop == NULL)
|
||||||
die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
|
die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(conn, conn_screen);
|
root_screen = xcb_aux_get_screen(conn, conn_screen);
|
||||||
root = root_screen->root;
|
root = root_screen->root;
|
||||||
@ -577,7 +577,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ ROOT_EVENT_MASK });
|
cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK});
|
||||||
check_error(conn, cookie, "Another window manager seems to be running");
|
check_error(conn, cookie, "Another window manager seems to be running");
|
||||||
|
|
||||||
xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
|
xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
|
||||||
@ -587,11 +587,11 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
|
DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
|
||||||
|
|
||||||
/* Place requests for the atoms we need as soon as possible */
|
/* Place requests for the atoms we need as soon as possible */
|
||||||
#define xmacro(atom) \
|
#define xmacro(atom) \
|
||||||
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
/* Initialize the Xlib connection */
|
/* Initialize the Xlib connection */
|
||||||
xlibdpy = xkbdpy = XOpenDisplay(NULL);
|
xlibdpy = xkbdpy = XOpenDisplay(NULL);
|
||||||
@ -613,7 +613,8 @@ int main(int argc, char *argv[]) {
|
|||||||
cursor until the first client is launched). */
|
cursor until the first client is launched). */
|
||||||
if (xcursor_supported)
|
if (xcursor_supported)
|
||||||
xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
||||||
else xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
else
|
||||||
|
xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
||||||
|
|
||||||
if (xkb_supported) {
|
if (xkb_supported) {
|
||||||
int errBase,
|
int errBase,
|
||||||
@ -626,15 +627,13 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int i1;
|
int i1;
|
||||||
if (!XkbQueryExtension(xkbdpy,&i1,&xkb_event_base,&errBase,&major,&minor)) {
|
if (!XkbQueryExtension(xkbdpy, &i1, &xkb_event_base, &errBase, &major, &minor)) {
|
||||||
fprintf(stderr, "XKB not supported by X-server\n");
|
fprintf(stderr, "XKB not supported by X-server\n");
|
||||||
xkb_supported = false;
|
xkb_supported = false;
|
||||||
}
|
}
|
||||||
/* end of ugliness */
|
/* end of ugliness */
|
||||||
|
|
||||||
if (xkb_supported && !XkbSelectEvents(xkbdpy, XkbUseCoreKbd,
|
if (xkb_supported && !XkbSelectEvents(xkbdpy, XkbUseCoreKbd, XkbMapNotifyMask | XkbStateNotifyMask, XkbMapNotifyMask | XkbStateNotifyMask)) {
|
||||||
XkbMapNotifyMask | XkbStateNotifyMask,
|
|
||||||
XkbMapNotifyMask | XkbStateNotifyMask)) {
|
|
||||||
fprintf(stderr, "Could not set XKB event mask\n");
|
fprintf(stderr, "Could not set XKB event mask\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -642,19 +641,19 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
restore_connect();
|
restore_connect();
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define xmacro(name) \
|
#define xmacro(name) \
|
||||||
do { \
|
do { \
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
|
||||||
if (!reply) { \
|
if (!reply) { \
|
||||||
ELOG("Could not get atom " #name "\n"); \
|
ELOG("Could not get atom " #name "\n"); \
|
||||||
exit(-1); \
|
exit(-1); \
|
||||||
} \
|
} \
|
||||||
A_ ## name = reply->atom; \
|
A_##name = reply->atom; \
|
||||||
free(reply); \
|
free(reply); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
property_handlers_init();
|
property_handlers_init();
|
||||||
|
|
||||||
@ -777,7 +776,6 @@ int main(int argc, char *argv[]) {
|
|||||||
ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
|
ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
|
||||||
ev_io_start(main_loop, xcb_watcher);
|
ev_io_start(main_loop, xcb_watcher);
|
||||||
|
|
||||||
|
|
||||||
if (xkb_supported) {
|
if (xkb_supported) {
|
||||||
ev_io_init(xkb, xkb_got_event, ConnectionNumber(xkbdpy), EV_READ);
|
ev_io_init(xkb, xkb_got_event, ConnectionNumber(xkbdpy), EV_READ);
|
||||||
ev_io_start(main_loop, xkb);
|
ev_io_start(main_loop, xkb);
|
||||||
@ -843,11 +841,11 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
|
xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
|
||||||
|
|
||||||
xcb_create_gc(conn, gc, root->root,
|
xcb_create_gc(conn, gc, root->root,
|
||||||
XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
|
XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
|
||||||
(uint32_t[]){ XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS });
|
(uint32_t[]) {XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
|
||||||
|
|
||||||
xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
|
xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
|
||||||
xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){ pixmap });
|
xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]) {pixmap});
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
xcb_free_gc(conn, gc);
|
xcb_free_gc(conn, gc);
|
||||||
xcb_free_pixmap(conn, pixmap);
|
xcb_free_pixmap(conn, pixmap);
|
||||||
@ -886,7 +884,7 @@ int main(int argc, char *argv[]) {
|
|||||||
/* Autostarting exec-lines */
|
/* Autostarting exec-lines */
|
||||||
if (autostart) {
|
if (autostart) {
|
||||||
struct Autostart *exec;
|
struct Autostart *exec;
|
||||||
TAILQ_FOREACH(exec, &autostarts, autostarts) {
|
TAILQ_FOREACH (exec, &autostarts, autostarts) {
|
||||||
LOG("auto-starting %s\n", exec->command);
|
LOG("auto-starting %s\n", exec->command);
|
||||||
start_application(exec->command, exec->no_startup_id);
|
start_application(exec->command, exec->no_startup_id);
|
||||||
}
|
}
|
||||||
@ -894,18 +892,18 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* Autostarting exec_always-lines */
|
/* Autostarting exec_always-lines */
|
||||||
struct Autostart *exec_always;
|
struct Autostart *exec_always;
|
||||||
TAILQ_FOREACH(exec_always, &autostarts_always, autostarts_always) {
|
TAILQ_FOREACH (exec_always, &autostarts_always, autostarts_always) {
|
||||||
LOG("auto-starting (always!) %s\n", exec_always->command);
|
LOG("auto-starting (always!) %s\n", exec_always->command);
|
||||||
start_application(exec_always->command, exec_always->no_startup_id);
|
start_application(exec_always->command, exec_always->no_startup_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start i3bar processes for all configured bars */
|
/* Start i3bar processes for all configured bars */
|
||||||
Barconfig *barconfig;
|
Barconfig *barconfig;
|
||||||
TAILQ_FOREACH(barconfig, &barconfigs, configs) {
|
TAILQ_FOREACH (barconfig, &barconfigs, configs) {
|
||||||
char *command = NULL;
|
char *command = NULL;
|
||||||
sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
|
sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
|
||||||
barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
|
barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
|
||||||
barconfig->id, current_socketpath);
|
barconfig->id, current_socketpath);
|
||||||
LOG("Starting bar process: %s\n", command);
|
LOG("Starting bar process: %s\n", command);
|
||||||
start_application(command, true);
|
start_application(command, true);
|
||||||
free(command);
|
free(command);
|
||||||
|
36
src/manage.c
36
src/manage.c
@ -56,7 +56,7 @@ void restore_geometry(void) {
|
|||||||
DLOG("Restoring geometry\n");
|
DLOG("Restoring geometry\n");
|
||||||
|
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons)
|
TAILQ_FOREACH (con, &all_cons, all_cons)
|
||||||
if (con->window) {
|
if (con->window) {
|
||||||
DLOG("Re-adding X11 border of %d px\n", con->border_width);
|
DLOG("Re-adding X11 border of %d px\n", con->border_width);
|
||||||
con->window_rect.width += (2 * con->border_width);
|
con->window_rect.width += (2 * con->border_width);
|
||||||
@ -69,7 +69,7 @@ void restore_geometry(void) {
|
|||||||
|
|
||||||
/* Strictly speaking, this line doesn’t really belong here, but since we
|
/* Strictly speaking, this line doesn’t really belong here, but since we
|
||||||
* are syncing, let’s un-register as a window manager first */
|
* are syncing, let’s un-register as a window manager first */
|
||||||
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT });
|
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
|
||||||
|
|
||||||
/* Make sure our changes reach the X server, we restart/exit now */
|
/* Make sure our changes reach the X server, we restart/exit now */
|
||||||
xcb_aux_sync(conn);
|
xcb_aux_sync(conn);
|
||||||
@ -81,17 +81,16 @@ void restore_geometry(void) {
|
|||||||
*/
|
*/
|
||||||
void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
|
void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
|
||||||
bool needs_to_be_mapped) {
|
bool needs_to_be_mapped) {
|
||||||
xcb_drawable_t d = { window };
|
xcb_drawable_t d = {window};
|
||||||
xcb_get_geometry_cookie_t geomc;
|
xcb_get_geometry_cookie_t geomc;
|
||||||
xcb_get_geometry_reply_t *geom;
|
xcb_get_geometry_reply_t *geom;
|
||||||
xcb_get_window_attributes_reply_t *attr = NULL;
|
xcb_get_window_attributes_reply_t *attr = NULL;
|
||||||
|
|
||||||
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
|
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
|
||||||
utf8_title_cookie, title_cookie,
|
utf8_title_cookie, title_cookie,
|
||||||
class_cookie, leader_cookie, transient_cookie,
|
class_cookie, leader_cookie, transient_cookie,
|
||||||
role_cookie, startup_id_cookie, wm_hints_cookie,
|
role_cookie, startup_id_cookie, wm_hints_cookie,
|
||||||
wm_normal_hints_cookie, motif_wm_hints_cookie;
|
wm_normal_hints_cookie, motif_wm_hints_cookie;
|
||||||
|
|
||||||
|
|
||||||
geomc = xcb_get_geometry(conn, d);
|
geomc = xcb_get_geometry(conn, d);
|
||||||
|
|
||||||
@ -270,7 +269,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||||||
if (!workspace_is_visible(assigned_ws))
|
if (!workspace_is_visible(assigned_ws))
|
||||||
urgency_hint = true;
|
urgency_hint = true;
|
||||||
}
|
}
|
||||||
/* TODO: handle assignments with type == A_TO_OUTPUT */
|
/* TODO: handle assignments with type == A_TO_OUTPUT */
|
||||||
} else if (startup_ws) {
|
} else if (startup_ws) {
|
||||||
/* If it’s not assigned, but was started on a specific workspace,
|
/* If it’s not assigned, but was started on a specific workspace,
|
||||||
* we want to open it there */
|
* we want to open it there */
|
||||||
@ -279,14 +278,16 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||||||
DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
|
DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
|
||||||
if (nc->type == CT_WORKSPACE)
|
if (nc->type == CT_WORKSPACE)
|
||||||
nc = tree_open_con(nc, cwindow);
|
nc = tree_open_con(nc, cwindow);
|
||||||
else nc = tree_open_con(nc->parent, cwindow);
|
else
|
||||||
|
nc = tree_open_con(nc->parent, cwindow);
|
||||||
} else {
|
} else {
|
||||||
/* If not, insert it at the currently focused position */
|
/* If not, insert it at the currently focused position */
|
||||||
if (focused->type == CT_CON && con_accepts_window(focused)) {
|
if (focused->type == CT_CON && con_accepts_window(focused)) {
|
||||||
LOG("using current container, focused = %p, focused->name = %s\n",
|
LOG("using current container, focused = %p, focused->name = %s\n",
|
||||||
focused, focused->name);
|
focused, focused->name);
|
||||||
nc = focused;
|
nc = focused;
|
||||||
} else nc = tree_open_con(NULL, cwindow);
|
} else
|
||||||
|
nc = tree_open_con(NULL, cwindow);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* M_BELOW inserts the new window as a child of the one which was
|
/* M_BELOW inserts the new window as a child of the one which was
|
||||||
@ -349,9 +350,12 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||||||
if (workspace_is_visible(ws) && current_output == target_output) {
|
if (workspace_is_visible(ws) && current_output == target_output) {
|
||||||
if (!match || !match->restart_mode) {
|
if (!match || !match->restart_mode) {
|
||||||
set_focus = true;
|
set_focus = true;
|
||||||
} else DLOG("not focusing, matched with restart_mode == true\n");
|
} else
|
||||||
} else DLOG("workspace not visible, not focusing\n");
|
DLOG("not focusing, matched with restart_mode == true\n");
|
||||||
} else DLOG("dock, not focusing\n");
|
} else
|
||||||
|
DLOG("workspace not visible, not focusing\n");
|
||||||
|
} else
|
||||||
|
DLOG("dock, not focusing\n");
|
||||||
} else {
|
} else {
|
||||||
DLOG("fs = %p, ws = %p, not focusing\n", fs, ws);
|
DLOG("fs = %p, ws = %p, not focusing\n", fs, ws);
|
||||||
/* Insert the new container in focus stack *after* the currently
|
/* Insert the new container in focus stack *after* the currently
|
||||||
@ -430,7 +434,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||||||
* which are not managed by the wm anyways). We store the original geometry
|
* which are not managed by the wm anyways). We store the original geometry
|
||||||
* here because it’s used for dock clients. */
|
* here because it’s used for dock clients. */
|
||||||
if (nc->geometry.width == 0)
|
if (nc->geometry.width == 0)
|
||||||
nc->geometry = (Rect){ geom->x, geom->y, geom->width, geom->height };
|
nc->geometry = (Rect) {geom->x, geom->y, geom->width, geom->height};
|
||||||
|
|
||||||
if (want_floating) {
|
if (want_floating) {
|
||||||
DLOG("geometry = %d x %d\n", nc->geometry.width, nc->geometry.height);
|
DLOG("geometry = %d x %d\n", nc->geometry.width, nc->geometry.height);
|
||||||
|
31
src/match.c
31
src/match.c
@ -16,10 +16,8 @@
|
|||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
/* From sys/time.h, not sure if it’s available on all systems. */
|
/* From sys/time.h, not sure if it’s available on all systems. */
|
||||||
# define _i3_timercmp(a, b, CMP) \
|
#define _i3_timercmp(a, b, CMP) \
|
||||||
(((a).tv_sec == (b).tv_sec) ? \
|
(((a).tv_sec == (b).tv_sec) ? ((a).tv_usec CMP(b).tv_usec) : ((a).tv_sec CMP(b).tv_sec))
|
||||||
((a).tv_usec CMP (b).tv_usec) : \
|
|
||||||
((a).tv_sec CMP (b).tv_sec))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the Match data structure. This function is necessary because the
|
* Initializes the Match data structure. This function is necessary because the
|
||||||
@ -65,10 +63,11 @@ void match_copy(Match *dest, Match *src) {
|
|||||||
/* The DUPLICATE_REGEX macro creates a new regular expression from the
|
/* The DUPLICATE_REGEX macro creates a new regular expression from the
|
||||||
* ->pattern of the old one. It therefore does use a little more memory then
|
* ->pattern of the old one. It therefore does use a little more memory then
|
||||||
* with a refcounting system, but it’s easier this way. */
|
* with a refcounting system, but it’s easier this way. */
|
||||||
#define DUPLICATE_REGEX(field) do { \
|
#define DUPLICATE_REGEX(field) \
|
||||||
if (src->field != NULL) \
|
do { \
|
||||||
dest->field = regex_new(src->field->pattern); \
|
if (src->field != NULL) \
|
||||||
} while (0)
|
dest->field = regex_new(src->field->pattern); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
DUPLICATE_REGEX(title);
|
DUPLICATE_REGEX(title);
|
||||||
DUPLICATE_REGEX(mark);
|
DUPLICATE_REGEX(mark);
|
||||||
@ -137,9 +136,9 @@ bool match_matches_window(Match *match, i3Window *window) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* if we find a window that is newer than this one, bail */
|
/* if we find a window that is newer than this one, bail */
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
if ((con->window != NULL) &&
|
if ((con->window != NULL) &&
|
||||||
_i3_timercmp(con->window->urgent, window->urgent, >)) {
|
_i3_timercmp(con->window->urgent, window->urgent, > )) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,10 +151,10 @@ bool match_matches_window(Match *match, i3Window *window) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* if we find a window that is older than this one (and not 0), bail */
|
/* if we find a window that is older than this one (and not 0), bail */
|
||||||
TAILQ_FOREACH(con, &all_cons, all_cons) {
|
TAILQ_FOREACH (con, &all_cons, all_cons) {
|
||||||
if ((con->window != NULL) &&
|
if ((con->window != NULL) &&
|
||||||
(con->window->urgent.tv_sec != 0) &&
|
(con->window->urgent.tv_sec != 0) &&
|
||||||
_i3_timercmp(con->window->urgent, window->urgent, <)) {
|
_i3_timercmp(con->window->urgent, window->urgent, < )) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,10 +163,10 @@ bool match_matches_window(Match *match, i3Window *window) {
|
|||||||
|
|
||||||
if (match->dock != -1) {
|
if (match->dock != -1) {
|
||||||
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
|
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
|
||||||
(window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||
|
(window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||
|
||||||
((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) &&
|
((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) &&
|
||||||
match->dock == M_DOCK_ANY) ||
|
match->dock == M_DOCK_ANY) ||
|
||||||
(window->dock == W_NODOCK && match->dock == M_NODOCK)) {
|
(window->dock == W_NODOCK && match->dock == M_NODOCK)) {
|
||||||
LOG("dock status matches\n");
|
LOG("dock status matches\n");
|
||||||
} else {
|
} else {
|
||||||
LOG("dock status does not match\n");
|
LOG("dock status does not match\n");
|
||||||
|
28
src/move.c
28
src/move.c
@ -11,7 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
typedef enum { BEFORE, AFTER } position_t;
|
typedef enum { BEFORE,
|
||||||
|
AFTER } position_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function detaches 'con' from its parent and inserts it either before or
|
* This function detaches 'con' from its parent and inserts it either before or
|
||||||
@ -184,22 +185,22 @@ void tree_move(int direction) {
|
|||||||
if (same_orientation == con->parent) {
|
if (same_orientation == con->parent) {
|
||||||
DLOG("We are in the same container\n");
|
DLOG("We are in the same container\n");
|
||||||
Con *swap;
|
Con *swap;
|
||||||
if ((swap = (direction == D_LEFT || direction == D_UP ?
|
if ((swap = (direction == D_LEFT || direction == D_UP ? TAILQ_PREV(con, nodes_head, nodes) : TAILQ_NEXT(con, nodes)))) {
|
||||||
TAILQ_PREV(con, nodes_head, nodes) :
|
|
||||||
TAILQ_NEXT(con, nodes)))) {
|
|
||||||
if (!con_is_leaf(swap)) {
|
if (!con_is_leaf(swap)) {
|
||||||
DLOG("Moving into our bordering branch\n");
|
DLOG("Moving into our bordering branch\n");
|
||||||
target = con_descend_direction(swap, direction);
|
target = con_descend_direction(swap, direction);
|
||||||
position = (con_orientation(target->parent) != o ||
|
position = (con_orientation(target->parent) != o ||
|
||||||
direction == D_UP ||
|
direction == D_UP ||
|
||||||
direction == D_LEFT ?
|
direction == D_LEFT
|
||||||
AFTER : BEFORE);
|
? AFTER
|
||||||
|
: BEFORE);
|
||||||
insert_con_into(con, target, position);
|
insert_con_into(con, target, position);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (direction == D_LEFT || direction == D_UP)
|
if (direction == D_LEFT || direction == D_UP)
|
||||||
TAILQ_SWAP(swap, con, &(swap->parent->nodes_head), nodes);
|
TAILQ_SWAP(swap, con, &(swap->parent->nodes_head), nodes);
|
||||||
else TAILQ_SWAP(con, swap, &(swap->parent->nodes_head), nodes);
|
else
|
||||||
|
TAILQ_SWAP(con, swap, &(swap->parent->nodes_head), nodes);
|
||||||
|
|
||||||
TAILQ_REMOVE(&(con->parent->focus_head), con, focused);
|
TAILQ_REMOVE(&(con->parent->focus_head), con, focused);
|
||||||
TAILQ_INSERT_HEAD(&(swap->parent->focus_head), con, focused);
|
TAILQ_INSERT_HEAD(&(swap->parent->focus_head), con, focused);
|
||||||
@ -236,17 +237,16 @@ void tree_move(int direction) {
|
|||||||
|
|
||||||
DLOG("above = %p\n", above);
|
DLOG("above = %p\n", above);
|
||||||
|
|
||||||
Con *next = (direction == D_UP || direction == D_LEFT ?
|
Con *next = (direction == D_UP || direction == D_LEFT ? TAILQ_PREV(above, nodes_head, nodes) : TAILQ_NEXT(above, nodes));
|
||||||
TAILQ_PREV(above, nodes_head, nodes) :
|
|
||||||
TAILQ_NEXT(above, nodes));
|
|
||||||
|
|
||||||
if (next && !con_is_leaf(next)) {
|
if (next && !con_is_leaf(next)) {
|
||||||
DLOG("Moving into the bordering branch of our adjacent container\n");
|
DLOG("Moving into the bordering branch of our adjacent container\n");
|
||||||
target = con_descend_direction(next, direction);
|
target = con_descend_direction(next, direction);
|
||||||
position = (con_orientation(target->parent) != o ||
|
position = (con_orientation(target->parent) != o ||
|
||||||
direction == D_UP ||
|
direction == D_UP ||
|
||||||
direction == D_LEFT ?
|
direction == D_LEFT
|
||||||
AFTER : BEFORE);
|
? AFTER
|
||||||
|
: BEFORE);
|
||||||
insert_con_into(con, target, position);
|
insert_con_into(con, target, position);
|
||||||
} else {
|
} else {
|
||||||
DLOG("Moving into container above\n");
|
DLOG("Moving into container above\n");
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
Con *output_get_content(Con *output) {
|
Con *output_get_content(Con *output) {
|
||||||
Con *child;
|
Con *child;
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(output->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(output->nodes_head), nodes)
|
||||||
if (child->type == CT_CON)
|
if (child->type == CT_CON)
|
||||||
return child;
|
return child;
|
||||||
|
|
||||||
|
105
src/randr.c
105
src/randr.c
@ -37,7 +37,7 @@ static bool randr_disabled = false;
|
|||||||
*/
|
*/
|
||||||
static Output *get_output_by_id(xcb_randr_output_t id) {
|
static Output *get_output_by_id(xcb_randr_output_t id) {
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs)
|
TAILQ_FOREACH (output, &outputs, outputs)
|
||||||
if (output->id == id)
|
if (output->id == id)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ static Output *get_output_by_id(xcb_randr_output_t id) {
|
|||||||
*/
|
*/
|
||||||
Output *get_output_by_name(const char *name) {
|
Output *get_output_by_name(const char *name) {
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs)
|
TAILQ_FOREACH (output, &outputs, outputs)
|
||||||
if (output->active &&
|
if (output->active &&
|
||||||
strcasecmp(output->name, name) == 0)
|
strcasecmp(output->name, name) == 0)
|
||||||
return output;
|
return output;
|
||||||
@ -65,7 +65,7 @@ Output *get_output_by_name(const char *name) {
|
|||||||
Output *get_first_output(void) {
|
Output *get_first_output(void) {
|
||||||
Output *output;
|
Output *output;
|
||||||
|
|
||||||
TAILQ_FOREACH(output, &outputs, outputs)
|
TAILQ_FOREACH (output, &outputs, outputs)
|
||||||
if (output->active)
|
if (output->active)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
@ -79,11 +79,11 @@ Output *get_first_output(void) {
|
|||||||
*/
|
*/
|
||||||
Output *get_output_containing(unsigned int x, unsigned int y) {
|
Output *get_output_containing(unsigned int x, unsigned int y) {
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
|
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
|
||||||
x, y, output->rect.x, output->rect.y, output->rect.width, output->rect.height);
|
x, y, output->rect.x, output->rect.y, output->rect.width, output->rect.height);
|
||||||
if (x >= output->rect.x && x < (output->rect.x + output->rect.width) &&
|
if (x >= output->rect.x && x < (output->rect.x + output->rect.width) &&
|
||||||
y >= output->rect.y && y < (output->rect.y + output->rect.height))
|
y >= output->rect.y && y < (output->rect.y + output->rect.height))
|
||||||
return output;
|
return output;
|
||||||
@ -100,21 +100,20 @@ Output *get_output_containing(unsigned int x, unsigned int y) {
|
|||||||
* be many), we just return true or false for convenience.
|
* be many), we just return true or false for convenience.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool contained_by_output(Rect rect){
|
bool contained_by_output(Rect rect) {
|
||||||
Output *output;
|
Output *output;
|
||||||
int lx = rect.x, uy = rect.y;
|
int lx = rect.x, uy = rect.y;
|
||||||
int rx = rect.x + rect.width, by = rect.y + rect.height;
|
int rx = rect.x + rect.width, by = rect.y + rect.height;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
|
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
|
||||||
rect.x, rect.y, output->rect.x, output->rect.y, output->rect.width, output->rect.height);
|
rect.x, rect.y, output->rect.x, output->rect.y, output->rect.width, output->rect.height);
|
||||||
if (rx >= (int)output->rect.x && lx <= (int)(output->rect.x + output->rect.width) &&
|
if (rx >= (int)output->rect.x && lx <= (int)(output->rect.x + output->rect.width) &&
|
||||||
by >= (int)output->rect.y && uy <= (int)(output->rect.y + output->rect.height))
|
by >= (int)output->rect.y && uy <= (int)(output->rect.y + output->rect.height))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -163,26 +162,26 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
|
|||||||
Rect *cur = &(current->rect),
|
Rect *cur = &(current->rect),
|
||||||
*other;
|
*other;
|
||||||
Output *output,
|
Output *output,
|
||||||
*best = NULL;
|
*best = NULL;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
other = &(output->rect);
|
other = &(output->rect);
|
||||||
|
|
||||||
if ((direction == D_RIGHT && other->x > cur->x) ||
|
if ((direction == D_RIGHT && other->x > cur->x) ||
|
||||||
(direction == D_LEFT && other->x < cur->x)) {
|
(direction == D_LEFT && other->x < cur->x)) {
|
||||||
/* Skip the output when it doesn’t overlap the other one’s y
|
/* Skip the output when it doesn’t overlap the other one’s y
|
||||||
* coordinate at all. */
|
* coordinate at all. */
|
||||||
if ((other->y + other->height) <= cur->y ||
|
if ((other->y + other->height) <= cur->y ||
|
||||||
(cur->y + cur->height) <= other->y)
|
(cur->y + cur->height) <= other->y)
|
||||||
continue;
|
continue;
|
||||||
} else if ((direction == D_DOWN && other->y > cur->y) ||
|
} else if ((direction == D_DOWN && other->y > cur->y) ||
|
||||||
(direction == D_UP && other->y < cur->y)) {
|
(direction == D_UP && other->y < cur->y)) {
|
||||||
/* Skip the output when it doesn’t overlap the other one’s x
|
/* Skip the output when it doesn’t overlap the other one’s x
|
||||||
* coordinate at all. */
|
* coordinate at all. */
|
||||||
if ((other->x + other->width) <= cur->x ||
|
if ((other->x + other->width) <= cur->x ||
|
||||||
(cur->x + cur->width) <= other->x)
|
(cur->x + cur->width) <= other->x)
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
@ -197,9 +196,9 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
|
|||||||
/* Is this output better (closer to the current output) than our
|
/* Is this output better (closer to the current output) than our
|
||||||
* current best bet? */
|
* current best bet? */
|
||||||
if ((direction == D_RIGHT && other->x < best->rect.x) ||
|
if ((direction == D_RIGHT && other->x < best->rect.x) ||
|
||||||
(direction == D_LEFT && other->x > best->rect.x) ||
|
(direction == D_LEFT && other->x > best->rect.x) ||
|
||||||
(direction == D_DOWN && other->y < best->rect.y) ||
|
(direction == D_DOWN && other->y < best->rect.y) ||
|
||||||
(direction == D_UP && other->y > best->rect.y)) {
|
(direction == D_UP && other->y > best->rect.y)) {
|
||||||
best = output;
|
best = output;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -207,9 +206,9 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
|
|||||||
/* Is this output better (farther to the current output) than our
|
/* Is this output better (farther to the current output) than our
|
||||||
* current best bet? */
|
* current best bet? */
|
||||||
if ((direction == D_RIGHT && other->x > best->rect.x) ||
|
if ((direction == D_RIGHT && other->x > best->rect.x) ||
|
||||||
(direction == D_LEFT && other->x < best->rect.x) ||
|
(direction == D_LEFT && other->x < best->rect.x) ||
|
||||||
(direction == D_DOWN && other->y > best->rect.y) ||
|
(direction == D_DOWN && other->y > best->rect.y) ||
|
||||||
(direction == D_UP && other->y < best->rect.y)) {
|
(direction == D_UP && other->y < best->rect.y)) {
|
||||||
best = output;
|
best = output;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -257,7 +256,7 @@ void output_init_con(Output *output) {
|
|||||||
|
|
||||||
/* Search for a Con with that name directly below the root node. There
|
/* Search for a Con with that name directly below the root node. There
|
||||||
* might be one from a restored layout. */
|
* might be one from a restored layout. */
|
||||||
TAILQ_FOREACH(current, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(croot->nodes_head), nodes) {
|
||||||
if (strcmp(current->name, output->name) != 0)
|
if (strcmp(current->name, output->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -356,13 +355,13 @@ void output_init_con(Output *output) {
|
|||||||
void init_ws_for_output(Output *output, Con *content) {
|
void init_ws_for_output(Output *output, Con *content) {
|
||||||
/* go through all assignments and move the existing workspaces to this output */
|
/* go through all assignments and move the existing workspaces to this output */
|
||||||
struct Workspace_Assignment *assignment;
|
struct Workspace_Assignment *assignment;
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcmp(assignment->output, output->name) != 0)
|
if (strcmp(assignment->output, output->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check if this workspace actually exists */
|
/* check if this workspace actually exists */
|
||||||
Con *workspace = NULL, *out;
|
Con *workspace = NULL, *out;
|
||||||
TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (out, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(out),
|
GREP_FIRST(workspace, output_get_content(out),
|
||||||
!strcasecmp(child->name, assignment->name));
|
!strcasecmp(child->name, assignment->name));
|
||||||
if (workspace == NULL)
|
if (workspace == NULL)
|
||||||
@ -402,7 +401,7 @@ void init_ws_for_output(Output *output, Con *content) {
|
|||||||
Con *ws_out_content = output_get_content(workspace_out);
|
Con *ws_out_content = output_get_content(workspace_out);
|
||||||
|
|
||||||
Con *floating_con;
|
Con *floating_con;
|
||||||
TAILQ_FOREACH(floating_con, &(workspace->floating_head), floating_windows)
|
TAILQ_FOREACH (floating_con, &(workspace->floating_head), floating_windows)
|
||||||
/* NB: We use output->con here because content is not yet rendered,
|
/* NB: We use output->con here because content is not yet rendered,
|
||||||
* so it has a rect of {0, 0, 0, 0}. */
|
* so it has a rect of {0, 0, 0, 0}. */
|
||||||
floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect));
|
floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect));
|
||||||
@ -437,7 +436,7 @@ void init_ws_for_output(Output *output, Con *content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise, we create the first assigned ws for this output */
|
/* otherwise, we create the first assigned ws for this output */
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcmp(assignment->output, output->name) != 0)
|
if (strcmp(assignment->output, output->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -479,8 +478,8 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
|
|||||||
|
|
||||||
/* Fix the position of all floating windows on this output.
|
/* Fix the position of all floating windows on this output.
|
||||||
* The 'rect' of each workspace will be updated in src/render.c. */
|
* The 'rect' of each workspace will be updated in src/render.c. */
|
||||||
TAILQ_FOREACH(workspace, &(content->nodes_head), nodes) {
|
TAILQ_FOREACH (workspace, &(content->nodes_head), nodes) {
|
||||||
TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(workspace->floating_head), floating_windows) {
|
||||||
floating_fix_coordinates(child, &(workspace->rect), &(output->con->rect));
|
floating_fix_coordinates(child, &(workspace->rect), &(output->con->rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +488,7 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
|
|||||||
* the workspaces and their childs depending on output resolution. This is
|
* the workspaces and their childs depending on output resolution. This is
|
||||||
* only done for workspaces with maximum one child. */
|
* only done for workspaces with maximum one child. */
|
||||||
if (config.default_orientation == NO_ORIENTATION) {
|
if (config.default_orientation == NO_ORIENTATION) {
|
||||||
TAILQ_FOREACH(workspace, &(content->nodes_head), nodes) {
|
TAILQ_FOREACH (workspace, &(content->nodes_head), nodes) {
|
||||||
/* Workspaces with more than one child are left untouched because
|
/* Workspaces with more than one child are left untouched because
|
||||||
* we do not want to change an existing layout. */
|
* we do not want to change an existing layout. */
|
||||||
if (con_num_children(workspace) > 1)
|
if (con_num_children(workspace) > 1)
|
||||||
@ -528,8 +527,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
|
|||||||
new->primary = (primary && primary->output == id);
|
new->primary = (primary && primary->output == id);
|
||||||
FREE(new->name);
|
FREE(new->name);
|
||||||
sasprintf(&new->name, "%.*s",
|
sasprintf(&new->name, "%.*s",
|
||||||
xcb_randr_get_output_info_name_length(output),
|
xcb_randr_get_output_info_name_length(output),
|
||||||
xcb_randr_get_output_info_name(output));
|
xcb_randr_get_output_info_name(output));
|
||||||
|
|
||||||
DLOG("found output with name %s\n", new->name);
|
DLOG("found output with name %s\n", new->name);
|
||||||
|
|
||||||
@ -540,7 +539,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
|
|||||||
if (!existing) {
|
if (!existing) {
|
||||||
if (new->primary)
|
if (new->primary)
|
||||||
TAILQ_INSERT_HEAD(&outputs, new, outputs);
|
TAILQ_INSERT_HEAD(&outputs, new, outputs);
|
||||||
else TAILQ_INSERT_TAIL(&outputs, new, outputs);
|
else
|
||||||
|
TAILQ_INSERT_TAIL(&outputs, new, outputs);
|
||||||
} else if (new->active)
|
} else if (new->active)
|
||||||
new->to_be_disabled = true;
|
new->to_be_disabled = true;
|
||||||
return;
|
return;
|
||||||
@ -567,7 +567,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height,
|
DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height,
|
||||||
new->rect.x, new->rect.y);
|
new->rect.x, new->rect.y);
|
||||||
|
|
||||||
/* If we don’t need to change an existing output or if the output
|
/* If we don’t need to change an existing output or if the output
|
||||||
* does not exist in the first place, the case is simple: we either
|
* does not exist in the first place, the case is simple: we either
|
||||||
@ -576,7 +576,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
|
|||||||
if (!existing) {
|
if (!existing) {
|
||||||
if (new->primary)
|
if (new->primary)
|
||||||
TAILQ_INSERT_HEAD(&outputs, new, outputs);
|
TAILQ_INSERT_HEAD(&outputs, new, outputs);
|
||||||
else TAILQ_INSERT_TAIL(&outputs, new, outputs);
|
else
|
||||||
|
TAILQ_INSERT_TAIL(&outputs, new, outputs);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -610,7 +611,8 @@ void randr_query_outputs(void) {
|
|||||||
|
|
||||||
if ((primary = xcb_randr_get_output_primary_reply(conn, pcookie, NULL)) == NULL)
|
if ((primary = xcb_randr_get_output_primary_reply(conn, pcookie, NULL)) == NULL)
|
||||||
ELOG("Could not get RandR primary output\n");
|
ELOG("Could not get RandR primary output\n");
|
||||||
else DLOG("primary output is %08x\n", primary->output);
|
else
|
||||||
|
DLOG("primary output is %08x\n", primary->output);
|
||||||
if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) {
|
if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) {
|
||||||
disable_randr(conn);
|
disable_randr(conn);
|
||||||
return;
|
return;
|
||||||
@ -638,11 +640,11 @@ void randr_query_outputs(void) {
|
|||||||
|
|
||||||
/* Check for clones, disable the clones and reduce the mode to the
|
/* Check for clones, disable the clones and reduce the mode to the
|
||||||
* lowest common mode */
|
* lowest common mode */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->active || output->to_be_disabled)
|
if (!output->active || output->to_be_disabled)
|
||||||
continue;
|
continue;
|
||||||
DLOG("output %p / %s, position (%d, %d), checking for clones\n",
|
DLOG("output %p / %s, position (%d, %d), checking for clones\n",
|
||||||
output, output->name, output->rect.x, output->rect.y);
|
output, output->name, output->rect.x, output->rect.y);
|
||||||
|
|
||||||
for (other = output;
|
for (other = output;
|
||||||
other != TAILQ_END(&outputs);
|
other != TAILQ_END(&outputs);
|
||||||
@ -655,7 +657,7 @@ void randr_query_outputs(void) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
DLOG("output %p has the same position, his mode = %d x %d\n",
|
DLOG("output %p has the same position, his mode = %d x %d\n",
|
||||||
other, other->rect.width, other->rect.height);
|
other, other->rect.width, other->rect.height);
|
||||||
uint32_t width = min(other->rect.width, output->rect.width);
|
uint32_t width = min(other->rect.width, output->rect.width);
|
||||||
uint32_t height = min(other->rect.height, output->rect.height);
|
uint32_t height = min(other->rect.height, output->rect.height);
|
||||||
|
|
||||||
@ -670,8 +672,8 @@ void randr_query_outputs(void) {
|
|||||||
other->to_be_disabled = true;
|
other->to_be_disabled = true;
|
||||||
|
|
||||||
DLOG("new output mode %d x %d, other mode %d x %d\n",
|
DLOG("new output mode %d x %d, other mode %d x %d\n",
|
||||||
output->rect.width, output->rect.height,
|
output->rect.width, output->rect.height,
|
||||||
other->rect.width, other->rect.height);
|
other->rect.width, other->rect.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,7 +681,7 @@ void randr_query_outputs(void) {
|
|||||||
* necessary because in the next step, a clone might get disabled. Example:
|
* necessary because in the next step, a clone might get disabled. Example:
|
||||||
* LVDS1 active, VGA1 gets activated as a clone of LVDS1 (has no con).
|
* LVDS1 active, VGA1 gets activated as a clone of LVDS1 (has no con).
|
||||||
* LVDS1 gets disabled. */
|
* LVDS1 gets disabled. */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (output->active && output->con == NULL) {
|
if (output->active && output->con == NULL) {
|
||||||
DLOG("Need to initialize a Con for output %s\n", output->name);
|
DLOG("Need to initialize a Con for output %s\n", output->name);
|
||||||
output_init_con(output);
|
output_init_con(output);
|
||||||
@ -689,7 +691,7 @@ void randr_query_outputs(void) {
|
|||||||
|
|
||||||
/* Handle outputs which have a new mode or are disabled now (either
|
/* Handle outputs which have a new mode or are disabled now (either
|
||||||
* because the user disabled them or because they are clones) */
|
* because the user disabled them or because they are clones) */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (output->to_be_disabled) {
|
if (output->to_be_disabled) {
|
||||||
output->active = false;
|
output->active = false;
|
||||||
DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name);
|
DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name);
|
||||||
@ -729,7 +731,7 @@ void randr_query_outputs(void) {
|
|||||||
con_attach(current, first_content, false);
|
con_attach(current, first_content, false);
|
||||||
DLOG("Fixing the coordinates of floating containers\n");
|
DLOG("Fixing the coordinates of floating containers\n");
|
||||||
Con *floating_con;
|
Con *floating_con;
|
||||||
TAILQ_FOREACH(floating_con, &(current->floating_head), floating_windows)
|
TAILQ_FOREACH (floating_con, &(current->floating_head), floating_windows)
|
||||||
floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect));
|
floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect));
|
||||||
DLOG("Done, next\n");
|
DLOG("Done, next\n");
|
||||||
}
|
}
|
||||||
@ -743,7 +745,7 @@ void randr_query_outputs(void) {
|
|||||||
|
|
||||||
/* 3: move the dock clients to the first output */
|
/* 3: move the dock clients to the first output */
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(output->con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(output->con->nodes_head), nodes) {
|
||||||
if (child->type != CT_DOCKAREA)
|
if (child->type != CT_DOCKAREA)
|
||||||
continue;
|
continue;
|
||||||
DLOG("Handling dock con %p\n", child);
|
DLOG("Handling dock con %p\n", child);
|
||||||
@ -786,7 +788,7 @@ void randr_query_outputs(void) {
|
|||||||
get_first_output();
|
get_first_output();
|
||||||
|
|
||||||
/* Just go through each active output and assign one workspace */
|
/* Just go through each active output and assign one workspace */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
Con *content = output_get_content(output->con);
|
Con *content = output_get_content(output->con);
|
||||||
@ -797,7 +799,7 @@ void randr_query_outputs(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Focus the primary screen, if possible */
|
/* Focus the primary screen, if possible */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH (output, &outputs, outputs) {
|
||||||
if (!output->primary || !output->con)
|
if (!output->primary || !output->con)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -824,16 +826,17 @@ void randr_init(int *event_base) {
|
|||||||
if (!extreply->present) {
|
if (!extreply->present) {
|
||||||
disable_randr(conn);
|
disable_randr(conn);
|
||||||
return;
|
return;
|
||||||
} else randr_query_outputs();
|
} else
|
||||||
|
randr_query_outputs();
|
||||||
|
|
||||||
if (event_base != NULL)
|
if (event_base != NULL)
|
||||||
*event_base = extreply->first_event;
|
*event_base = extreply->first_event;
|
||||||
|
|
||||||
xcb_randr_select_input(conn, root,
|
xcb_randr_select_input(conn, root,
|
||||||
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
|
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
|
||||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
|
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
|
||||||
XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
|
XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
|
||||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
|
XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
|
||||||
|
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
}
|
}
|
||||||
|
247
src/render.c
247
src/render.c
@ -41,7 +41,7 @@ static void render_l_output(Con *con) {
|
|||||||
/* Find the content container and ensure that there is exactly one. Also
|
/* Find the content container and ensure that there is exactly one. Also
|
||||||
* check for any non-CT_DOCKAREA clients. */
|
* check for any non-CT_DOCKAREA clients. */
|
||||||
Con *content = NULL;
|
Con *content = NULL;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (child->type == CT_CON) {
|
if (child->type == CT_CON) {
|
||||||
if (content != NULL) {
|
if (content != NULL) {
|
||||||
DLOG("More than one CT_CON on output container\n");
|
DLOG("More than one CT_CON on output container\n");
|
||||||
@ -77,19 +77,19 @@ static void render_l_output(Con *con) {
|
|||||||
|
|
||||||
/* First pass: determine the height of all CT_DOCKAREAs (the sum of their
|
/* First pass: determine the height of all CT_DOCKAREAs (the sum of their
|
||||||
* children) and figure out how many pixels we have left for the rest */
|
* children) and figure out how many pixels we have left for the rest */
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (child->type != CT_DOCKAREA)
|
if (child->type != CT_DOCKAREA)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
child->rect.height = 0;
|
child->rect.height = 0;
|
||||||
TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes)
|
TAILQ_FOREACH (dockchild, &(child->nodes_head), nodes)
|
||||||
child->rect.height += dockchild->geometry.height;
|
child->rect.height += dockchild->geometry.height;
|
||||||
|
|
||||||
height -= child->rect.height;
|
height -= child->rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second pass: Set the widths/heights */
|
/* Second pass: Set the widths/heights */
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
if (child->type == CT_CON) {
|
if (child->type == CT_CON) {
|
||||||
child->rect.x = x;
|
child->rect.x = x;
|
||||||
child->rect.y = y;
|
child->rect.y = y;
|
||||||
@ -109,7 +109,7 @@ static void render_l_output(Con *con) {
|
|||||||
y += child->rect.height;
|
y += child->rect.height;
|
||||||
|
|
||||||
DLOG("child at (%d, %d) with (%d x %d)\n",
|
DLOG("child at (%d, %d) with (%d x %d)\n",
|
||||||
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
|
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
|
||||||
x_raise_con(child);
|
x_raise_con(child);
|
||||||
render_con(child, false);
|
render_con(child, false);
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
/* depending on the border style, the rect of the child window
|
/* depending on the border style, the rect of the child window
|
||||||
* needs to be smaller */
|
* needs to be smaller */
|
||||||
Rect *inset = &(con->window_rect);
|
Rect *inset = &(con->window_rect);
|
||||||
*inset = (Rect){0, 0, con->rect.width, con->rect.height};
|
*inset = (Rect) {0, 0, con->rect.width, con->rect.height};
|
||||||
if (!render_fullscreen)
|
if (!render_fullscreen)
|
||||||
*inset = rect_add(*inset, con_border_style_rect(con));
|
*inset = rect_add(*inset, con_border_style_rect(con));
|
||||||
|
|
||||||
@ -218,19 +218,19 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
|
|
||||||
/* precalculate the sizes to be able to correct rounding errors */
|
/* precalculate the sizes to be able to correct rounding errors */
|
||||||
int sizes[children];
|
int sizes[children];
|
||||||
memset(sizes, 0, children*sizeof(int));
|
memset(sizes, 0, children * sizeof(int));
|
||||||
if ((con->layout == L_SPLITH || con->layout == L_SPLITV) && children > 0) {
|
if ((con->layout == L_SPLITH || con->layout == L_SPLITV) && children > 0) {
|
||||||
assert(!TAILQ_EMPTY(&con->nodes_head));
|
assert(!TAILQ_EMPTY(&con->nodes_head));
|
||||||
Con *child;
|
Con *child;
|
||||||
int i = 0, assigned = 0;
|
int i = 0, assigned = 0;
|
||||||
int total = con_orientation(con) == HORIZ ? rect.width : rect.height;
|
int total = con_orientation(con) == HORIZ ? rect.width : rect.height;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
double percentage = child->percent > 0.0 ? child->percent : 1.0 / children;
|
double percentage = child->percent > 0.0 ? child->percent : 1.0 / children;
|
||||||
assigned += sizes[i++] = percentage * total;
|
assigned += sizes[i++] = percentage * total;
|
||||||
}
|
}
|
||||||
assert(assigned == total ||
|
assert(assigned == total ||
|
||||||
(assigned > total && assigned - total <= children * 2) ||
|
(assigned > total && assigned - total <= children * 2) ||
|
||||||
(assigned < total && total - assigned <= children * 2));
|
(assigned < total && total - assigned <= children * 2));
|
||||||
int signal = assigned < total ? 1 : -1;
|
int signal = assigned < total ? 1 : -1;
|
||||||
while (assigned != total) {
|
while (assigned != total) {
|
||||||
for (i = 0; i < children && assigned != total; ++i) {
|
for (i = 0; i < children && assigned != total; ++i) {
|
||||||
@ -247,7 +247,7 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
render_l_output(con);
|
render_l_output(con);
|
||||||
} else if (con->type == CT_ROOT) {
|
} else if (con->type == CT_ROOT) {
|
||||||
Con *output;
|
Con *output;
|
||||||
TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(con->nodes_head), nodes) {
|
||||||
render_con(output, false);
|
render_con(output, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
* all times. This is important when the user places floating
|
* all times. This is important when the user places floating
|
||||||
* windows/containers so that they overlap on another output. */
|
* windows/containers so that they overlap on another output. */
|
||||||
DLOG("Rendering floating windows:\n");
|
DLOG("Rendering floating windows:\n");
|
||||||
TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(con->nodes_head), nodes) {
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
/* Get the active workspace of that output */
|
/* Get the active workspace of that output */
|
||||||
@ -268,7 +268,7 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
Con *workspace = TAILQ_FIRST(&(content->focus_head));
|
Con *workspace = TAILQ_FIRST(&(content->focus_head));
|
||||||
Con *fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
|
Con *fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(workspace->floating_head), floating_windows) {
|
||||||
/* Don’t render floating windows when there is a fullscreen window
|
/* Don’t render floating windows when there is a fullscreen window
|
||||||
* on that workspace. Necessary to make floating fullscreen work
|
* on that workspace. Necessary to make floating fullscreen work
|
||||||
* correctly (ticket #564). */
|
* correctly (ticket #564). */
|
||||||
@ -319,132 +319,131 @@ void render_con(Con *con, bool render_fullscreen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* FIXME: refactor this into separate functions: */
|
/* FIXME: refactor this into separate functions: */
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
assert(children > 0);
|
assert(children > 0);
|
||||||
|
|
||||||
/* default layout */
|
/* default layout */
|
||||||
if (con->layout == L_SPLITH || con->layout == L_SPLITV) {
|
if (con->layout == L_SPLITH || con->layout == L_SPLITV) {
|
||||||
if (con->layout == L_SPLITH) {
|
if (con->layout == L_SPLITH) {
|
||||||
child->rect.x = x;
|
child->rect.x = x;
|
||||||
child->rect.y = y;
|
child->rect.y = y;
|
||||||
child->rect.width = sizes[i];
|
child->rect.width = sizes[i];
|
||||||
child->rect.height = rect.height;
|
child->rect.height = rect.height;
|
||||||
x += child->rect.width;
|
x += child->rect.width;
|
||||||
} else {
|
} else {
|
||||||
|
child->rect.x = x;
|
||||||
|
child->rect.y = y;
|
||||||
|
child->rect.width = rect.width;
|
||||||
|
child->rect.height = sizes[i];
|
||||||
|
y += child->rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first we have the decoration, if this is a leaf node */
|
||||||
|
if (con_is_leaf(child)) {
|
||||||
|
if (child->border_style == BS_NORMAL) {
|
||||||
|
/* TODO: make a function for relative coords? */
|
||||||
|
child->deco_rect.x = child->rect.x - con->rect.x;
|
||||||
|
child->deco_rect.y = child->rect.y - con->rect.y;
|
||||||
|
|
||||||
|
child->rect.y += deco_height;
|
||||||
|
child->rect.height -= deco_height;
|
||||||
|
|
||||||
|
child->deco_rect.width = child->rect.width;
|
||||||
|
child->deco_rect.height = deco_height;
|
||||||
|
} else {
|
||||||
|
child->deco_rect.x = 0;
|
||||||
|
child->deco_rect.y = 0;
|
||||||
|
child->deco_rect.width = 0;
|
||||||
|
child->deco_rect.height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stacked layout */
|
||||||
|
else if (con->layout == L_STACKED) {
|
||||||
child->rect.x = x;
|
child->rect.x = x;
|
||||||
child->rect.y = y;
|
child->rect.y = y;
|
||||||
child->rect.width = rect.width;
|
child->rect.width = rect.width;
|
||||||
child->rect.height = sizes[i];
|
child->rect.height = rect.height;
|
||||||
|
|
||||||
|
child->deco_rect.x = x - con->rect.x;
|
||||||
|
child->deco_rect.y = y - con->rect.y + (i * deco_height);
|
||||||
|
child->deco_rect.width = child->rect.width;
|
||||||
|
child->deco_rect.height = deco_height;
|
||||||
|
|
||||||
|
if (children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
|
||||||
|
child->rect.y += (deco_height * children);
|
||||||
|
child->rect.height -= (deco_height * children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tabbed layout */
|
||||||
|
else if (con->layout == L_TABBED) {
|
||||||
|
child->rect.x = x;
|
||||||
|
child->rect.y = y;
|
||||||
|
child->rect.width = rect.width;
|
||||||
|
child->rect.height = rect.height;
|
||||||
|
|
||||||
|
child->deco_rect.width = floor((float)child->rect.width / children);
|
||||||
|
child->deco_rect.x = x - con->rect.x + i * child->deco_rect.width;
|
||||||
|
child->deco_rect.y = y - con->rect.y;
|
||||||
|
|
||||||
|
/* Since the tab width may be something like 31,6 px per tab, we
|
||||||
|
* let the last tab have all the extra space (0,6 * children). */
|
||||||
|
if (i == (children - 1)) {
|
||||||
|
child->deco_rect.width += (child->rect.width - (child->deco_rect.x + child->deco_rect.width));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
|
||||||
|
child->rect.y += deco_height;
|
||||||
|
child->rect.height -= deco_height;
|
||||||
|
child->deco_rect.height = deco_height;
|
||||||
|
} else {
|
||||||
|
child->deco_rect.height = (child->border_style == BS_PIXEL ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dockarea layout */
|
||||||
|
else if (con->layout == L_DOCKAREA) {
|
||||||
|
child->rect.x = x;
|
||||||
|
child->rect.y = y;
|
||||||
|
child->rect.width = rect.width;
|
||||||
|
child->rect.height = child->geometry.height;
|
||||||
|
|
||||||
|
child->deco_rect.x = 0;
|
||||||
|
child->deco_rect.y = 0;
|
||||||
|
child->deco_rect.width = 0;
|
||||||
|
child->deco_rect.height = 0;
|
||||||
y += child->rect.height;
|
y += child->rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first we have the decoration, if this is a leaf node */
|
DLOG("child at (%d, %d) with (%d x %d)\n",
|
||||||
if (con_is_leaf(child)) {
|
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
|
||||||
if (child->border_style == BS_NORMAL) {
|
|
||||||
/* TODO: make a function for relative coords? */
|
|
||||||
child->deco_rect.x = child->rect.x - con->rect.x;
|
|
||||||
child->deco_rect.y = child->rect.y - con->rect.y;
|
|
||||||
|
|
||||||
child->rect.y += deco_height;
|
|
||||||
child->rect.height -= deco_height;
|
|
||||||
|
|
||||||
child->deco_rect.width = child->rect.width;
|
|
||||||
child->deco_rect.height = deco_height;
|
|
||||||
} else {
|
|
||||||
child->deco_rect.x = 0;
|
|
||||||
child->deco_rect.y = 0;
|
|
||||||
child->deco_rect.width = 0;
|
|
||||||
child->deco_rect.height = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stacked layout */
|
|
||||||
else if (con->layout == L_STACKED) {
|
|
||||||
child->rect.x = x;
|
|
||||||
child->rect.y = y;
|
|
||||||
child->rect.width = rect.width;
|
|
||||||
child->rect.height = rect.height;
|
|
||||||
|
|
||||||
child->deco_rect.x = x - con->rect.x;
|
|
||||||
child->deco_rect.y = y - con->rect.y + (i * deco_height);
|
|
||||||
child->deco_rect.width = child->rect.width;
|
|
||||||
child->deco_rect.height = deco_height;
|
|
||||||
|
|
||||||
if (children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
|
|
||||||
child->rect.y += (deco_height * children);
|
|
||||||
child->rect.height -= (deco_height * children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tabbed layout */
|
|
||||||
else if (con->layout == L_TABBED) {
|
|
||||||
child->rect.x = x;
|
|
||||||
child->rect.y = y;
|
|
||||||
child->rect.width = rect.width;
|
|
||||||
child->rect.height = rect.height;
|
|
||||||
|
|
||||||
child->deco_rect.width = floor((float)child->rect.width / children);
|
|
||||||
child->deco_rect.x = x - con->rect.x + i * child->deco_rect.width;
|
|
||||||
child->deco_rect.y = y - con->rect.y;
|
|
||||||
|
|
||||||
/* Since the tab width may be something like 31,6 px per tab, we
|
|
||||||
* let the last tab have all the extra space (0,6 * children). */
|
|
||||||
if (i == (children-1)) {
|
|
||||||
child->deco_rect.width += (child->rect.width - (child->deco_rect.x + child->deco_rect.width));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
|
|
||||||
child->rect.y += deco_height;
|
|
||||||
child->rect.height -= deco_height;
|
|
||||||
child->deco_rect.height = deco_height;
|
|
||||||
} else {
|
|
||||||
child->deco_rect.height = (child->border_style == BS_PIXEL ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dockarea layout */
|
|
||||||
else if (con->layout == L_DOCKAREA) {
|
|
||||||
child->rect.x = x;
|
|
||||||
child->rect.y = y;
|
|
||||||
child->rect.width = rect.width;
|
|
||||||
child->rect.height = child->geometry.height;
|
|
||||||
|
|
||||||
child->deco_rect.x = 0;
|
|
||||||
child->deco_rect.y = 0;
|
|
||||||
child->deco_rect.width = 0;
|
|
||||||
child->deco_rect.height = 0;
|
|
||||||
y += child->rect.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG("child at (%d, %d) with (%d x %d)\n",
|
|
||||||
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
|
|
||||||
x_raise_con(child);
|
|
||||||
render_con(child, false);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in a stacking or tabbed container, we ensure the focused client is raised */
|
|
||||||
if (con->layout == L_STACKED || con->layout == L_TABBED) {
|
|
||||||
TAILQ_FOREACH_REVERSE(child, &(con->focus_head), focus_head, focused)
|
|
||||||
x_raise_con(child);
|
x_raise_con(child);
|
||||||
if ((child = TAILQ_FIRST(&(con->focus_head)))) {
|
render_con(child, false);
|
||||||
/* By rendering the stacked container again, we handle the case
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in a stacking or tabbed container, we ensure the focused client is raised */
|
||||||
|
if (con->layout == L_STACKED || con->layout == L_TABBED) {
|
||||||
|
TAILQ_FOREACH_REVERSE (child, &(con->focus_head), focus_head, focused)
|
||||||
|
x_raise_con(child);
|
||||||
|
if ((child = TAILQ_FIRST(&(con->focus_head)))) {
|
||||||
|
/* By rendering the stacked container again, we handle the case
|
||||||
* that we have a non-leaf-container inside the stack. In that
|
* that we have a non-leaf-container inside the stack. In that
|
||||||
* case, the children of the non-leaf-container need to be raised
|
* case, the children of the non-leaf-container need to be raised
|
||||||
* aswell. */
|
* aswell. */
|
||||||
render_con(child, false);
|
render_con(child, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (children != 1)
|
if (children != 1)
|
||||||
/* Raise the stack con itself. This will put the stack decoration on
|
/* Raise the stack con itself. This will put the stack decoration on
|
||||||
* top of every stack window. That way, when a new window is opened in
|
* top of every stack window. That way, when a new window is opened in
|
||||||
* the stack, the old window will not obscure part of the decoration
|
* the stack, the old window will not obscure part of the decoration
|
||||||
* (it’s unmapped afterwards). */
|
* (it’s unmapped afterwards). */
|
||||||
x_raise_con(con);
|
x_raise_con(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
src/resize.c
12
src/resize.c
@ -118,7 +118,7 @@ int resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
|
|||||||
/* Open a new window, the resizebar. Grab the pointer and move the window around
|
/* Open a new window, the resizebar. Grab the pointer and move the window around
|
||||||
as the user moves the pointer. */
|
as the user moves the pointer. */
|
||||||
xcb_window_t grabwin = create_window(conn, output->rect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
|
xcb_window_t grabwin = create_window(conn, output->rect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
|
||||||
XCB_WINDOW_CLASS_INPUT_ONLY, XCURSOR_CURSOR_POINTER, true, mask, values);
|
XCB_WINDOW_CLASS_INPUT_ONLY, XCURSOR_CURSOR_POINTER, true, mask, values);
|
||||||
|
|
||||||
/* Keep track of the coordinate orthogonal to motion so we can determine
|
/* Keep track of the coordinate orthogonal to motion so we can determine
|
||||||
* the length of the resize afterward. */
|
* the length of the resize afterward. */
|
||||||
@ -134,7 +134,7 @@ int resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
|
|||||||
helprect.height = second->rect.height;
|
helprect.height = second->rect.height;
|
||||||
initial_position = second->rect.x;
|
initial_position = second->rect.x;
|
||||||
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
|
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
|
||||||
second->rect.x, event->root_y);
|
second->rect.x, event->root_y);
|
||||||
} else {
|
} else {
|
||||||
helprect.x = second->rect.x;
|
helprect.x = second->rect.x;
|
||||||
helprect.y = second->rect.y;
|
helprect.y = second->rect.y;
|
||||||
@ -142,7 +142,7 @@ int resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
|
|||||||
helprect.height = logical_px(2);
|
helprect.height = logical_px(2);
|
||||||
initial_position = second->rect.y;
|
initial_position = second->rect.y;
|
||||||
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
|
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
|
||||||
event->root_x, second->rect.y);
|
event->root_x, second->rect.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = XCB_CW_BACK_PIXEL;
|
mask = XCB_CW_BACK_PIXEL;
|
||||||
@ -152,9 +152,7 @@ int resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
|
|||||||
values[1] = 1;
|
values[1] = 1;
|
||||||
|
|
||||||
xcb_window_t helpwin = create_window(conn, helprect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
|
xcb_window_t helpwin = create_window(conn, helprect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, (orientation == HORIZ ?
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, (orientation == HORIZ ? XCURSOR_CURSOR_RESIZE_HORIZONTAL : XCURSOR_CURSOR_RESIZE_VERTICAL), true, mask, values);
|
||||||
XCURSOR_CURSOR_RESIZE_HORIZONTAL :
|
|
||||||
XCURSOR_CURSOR_RESIZE_VERTICAL), true, mask, values);
|
|
||||||
|
|
||||||
xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin);
|
xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin);
|
||||||
|
|
||||||
@ -163,7 +161,7 @@ int resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
|
|||||||
/* `new_position' will be updated by the `resize_callback'. */
|
/* `new_position' will be updated by the `resize_callback'. */
|
||||||
new_position = initial_position;
|
new_position = initial_position;
|
||||||
|
|
||||||
const struct callback_params params = { orientation, output, helpwin, &new_position };
|
const struct callback_params params = {orientation, output, helpwin, &new_position};
|
||||||
|
|
||||||
/* `drag_pointer' blocks until the drag is completed. */
|
/* `drag_pointer' blocks until the drag is completed. */
|
||||||
drag_result_t drag_result = drag_pointer(NULL, event, grabwin, BORDER_TOP, 0, resize_callback, ¶ms);
|
drag_result_t drag_result = drag_pointer(NULL, event, grabwin, BORDER_TOP, 0, resize_callback, ¶ms);
|
||||||
|
@ -60,7 +60,7 @@ static void restore_xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
|||||||
|
|
||||||
while ((event = xcb_poll_for_event(restore_conn)) != NULL) {
|
while ((event = xcb_poll_for_event(restore_conn)) != NULL) {
|
||||||
if (event->response_type == 0) {
|
if (event->response_type == 0) {
|
||||||
xcb_generic_error_t *error = (xcb_generic_error_t*)event;
|
xcb_generic_error_t *error = (xcb_generic_error_t *)event;
|
||||||
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
|
||||||
error->sequence, error->error_code);
|
error->sequence, error->error_code);
|
||||||
free(event);
|
free(event);
|
||||||
@ -125,9 +125,9 @@ void restore_connect(void) {
|
|||||||
|
|
||||||
static void update_placeholder_contents(placeholder_state *state) {
|
static void update_placeholder_contents(placeholder_state *state) {
|
||||||
xcb_change_gc(restore_conn, state->gc, XCB_GC_FOREGROUND,
|
xcb_change_gc(restore_conn, state->gc, XCB_GC_FOREGROUND,
|
||||||
(uint32_t[]) { config.client.placeholder.background });
|
(uint32_t[]) {config.client.placeholder.background});
|
||||||
xcb_poly_fill_rectangle(restore_conn, state->pixmap, state->gc, 1,
|
xcb_poly_fill_rectangle(restore_conn, state->pixmap, state->gc, 1,
|
||||||
(xcb_rectangle_t[]) { { 0, 0, state->rect.width, state->rect.height } });
|
(xcb_rectangle_t[]) {{0, 0, state->rect.width, state->rect.height}});
|
||||||
|
|
||||||
// TODO: make i3font functions per-connection, at least these two for now…?
|
// TODO: make i3font functions per-connection, at least these two for now…?
|
||||||
xcb_flush(restore_conn);
|
xcb_flush(restore_conn);
|
||||||
@ -137,17 +137,15 @@ static void update_placeholder_contents(placeholder_state *state) {
|
|||||||
|
|
||||||
Match *swallows;
|
Match *swallows;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
TAILQ_FOREACH(swallows, &(state->con->swallow_head), matches) {
|
TAILQ_FOREACH (swallows, &(state->con->swallow_head), matches) {
|
||||||
char *serialized = NULL;
|
char *serialized = NULL;
|
||||||
|
|
||||||
#define APPEND_REGEX(re_name) do { \
|
#define APPEND_REGEX(re_name) \
|
||||||
if (swallows->re_name != NULL) { \
|
do { \
|
||||||
sasprintf(&serialized, "%s%s" #re_name "=\"%s\"", \
|
if (swallows->re_name != NULL) { \
|
||||||
(serialized ? serialized : "["), \
|
sasprintf(&serialized, "%s%s" #re_name "=\"%s\"", (serialized ? serialized : "["), (serialized ? " " : ""), swallows->re_name->pattern); \
|
||||||
(serialized ? " " : ""), \
|
} \
|
||||||
swallows->re_name->pattern); \
|
} while (0)
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
APPEND_REGEX(class);
|
APPEND_REGEX(class);
|
||||||
APPEND_REGEX(instance);
|
APPEND_REGEX(instance);
|
||||||
@ -184,18 +182,18 @@ static void open_placeholder_window(Con *con) {
|
|||||||
if (con_is_leaf(con) &&
|
if (con_is_leaf(con) &&
|
||||||
(con->window == NULL || con->window->id == XCB_NONE)) {
|
(con->window == NULL || con->window->id == XCB_NONE)) {
|
||||||
xcb_window_t placeholder = create_window(
|
xcb_window_t placeholder = create_window(
|
||||||
restore_conn,
|
restore_conn,
|
||||||
con->rect,
|
con->rect,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCURSOR_CURSOR_POINTER,
|
XCURSOR_CURSOR_POINTER,
|
||||||
true,
|
true,
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
config.client.placeholder.background,
|
config.client.placeholder.background,
|
||||||
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
||||||
});
|
});
|
||||||
/* Set the same name as was stored in the layout file. While perhaps
|
/* Set the same name as was stored in the layout file. While perhaps
|
||||||
* slightly confusing in the first instant, this brings additional
|
* slightly confusing in the first instant, this brings additional
|
||||||
* clarity to which placeholder is waiting for which actual window. */
|
* clarity to which placeholder is waiting for which actual window. */
|
||||||
@ -212,7 +210,7 @@ static void open_placeholder_window(Con *con) {
|
|||||||
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
|
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
|
||||||
state->window, state->rect.width, state->rect.height);
|
state->window, state->rect.width, state->rect.height);
|
||||||
state->gc = xcb_generate_id(restore_conn);
|
state->gc = xcb_generate_id(restore_conn);
|
||||||
xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){ 0 });
|
xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0});
|
||||||
update_placeholder_contents(state);
|
update_placeholder_contents(state);
|
||||||
TAILQ_INSERT_TAIL(&state_head, state, state);
|
TAILQ_INSERT_TAIL(&state_head, state, state);
|
||||||
|
|
||||||
@ -224,10 +222,10 @@ static void open_placeholder_window(Con *con) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
|
||||||
open_placeholder_window(child);
|
open_placeholder_window(child);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
|
||||||
open_placeholder_window(child);
|
open_placeholder_window(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,10 +239,10 @@ static void open_placeholder_window(Con *con) {
|
|||||||
*/
|
*/
|
||||||
void restore_open_placeholder_windows(Con *parent) {
|
void restore_open_placeholder_windows(Con *parent) {
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(parent->nodes_head), nodes) {
|
TAILQ_FOREACH (child, &(parent->nodes_head), nodes) {
|
||||||
open_placeholder_window(child);
|
open_placeholder_window(child);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(child, &(parent->floating_head), floating_windows) {
|
TAILQ_FOREACH (child, &(parent->floating_head), floating_windows) {
|
||||||
open_placeholder_window(child);
|
open_placeholder_window(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +258,7 @@ void restore_open_placeholder_windows(Con *parent) {
|
|||||||
*/
|
*/
|
||||||
bool restore_kill_placeholder(xcb_window_t placeholder) {
|
bool restore_kill_placeholder(xcb_window_t placeholder) {
|
||||||
placeholder_state *state;
|
placeholder_state *state;
|
||||||
TAILQ_FOREACH(state, &state_head, state) {
|
TAILQ_FOREACH (state, &state_head, state) {
|
||||||
if (state->window != placeholder)
|
if (state->window != placeholder)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -279,7 +277,7 @@ bool restore_kill_placeholder(xcb_window_t placeholder) {
|
|||||||
|
|
||||||
static void expose_event(xcb_expose_event_t *event) {
|
static void expose_event(xcb_expose_event_t *event) {
|
||||||
placeholder_state *state;
|
placeholder_state *state;
|
||||||
TAILQ_FOREACH(state, &state_head, state) {
|
TAILQ_FOREACH (state, &state_head, state) {
|
||||||
if (state->window != event->window)
|
if (state->window != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -307,7 +305,7 @@ static void expose_event(xcb_expose_event_t *event) {
|
|||||||
*/
|
*/
|
||||||
static void configure_notify(xcb_configure_notify_event_t *event) {
|
static void configure_notify(xcb_configure_notify_event_t *event) {
|
||||||
placeholder_state *state;
|
placeholder_state *state;
|
||||||
TAILQ_FOREACH(state, &state_head, state) {
|
TAILQ_FOREACH (state, &state_head, state) {
|
||||||
if (state->window != event->window)
|
if (state->window != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -324,7 +322,7 @@ static void configure_notify(xcb_configure_notify_event_t *event) {
|
|||||||
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
|
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
|
||||||
state->window, state->rect.width, state->rect.height);
|
state->window, state->rect.width, state->rect.height);
|
||||||
state->gc = xcb_generate_id(restore_conn);
|
state->gc = xcb_generate_id(restore_conn);
|
||||||
xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){ 0 });
|
xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0});
|
||||||
|
|
||||||
update_placeholder_contents(state);
|
update_placeholder_contents(state);
|
||||||
xcb_copy_area(restore_conn, state->pixmap, state->window, state->gc,
|
xcb_copy_area(restore_conn, state->pixmap, state->window, state->gc,
|
||||||
@ -339,10 +337,10 @@ static void configure_notify(xcb_configure_notify_event_t *event) {
|
|||||||
static void restore_handle_event(int type, xcb_generic_event_t *event) {
|
static void restore_handle_event(int type, xcb_generic_event_t *event) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
expose_event((xcb_expose_event_t*)event);
|
expose_event((xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_CONFIGURE_NOTIFY:
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
configure_notify((xcb_configure_notify_event_t*)event);
|
configure_notify((xcb_configure_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DLOG("Received unhandled X11 event of type %d\n", type);
|
DLOG("Received unhandled X11 event of type %d\n", type);
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
void scratchpad_move(Con *con) {
|
void scratchpad_move(Con *con) {
|
||||||
if (con->type == CT_WORKSPACE) {
|
if (con->type == CT_WORKSPACE) {
|
||||||
LOG("'move scratchpad' used on a workspace \"%s\". Calling it "
|
LOG("'move scratchpad' used on a workspace \"%s\". Calling it "
|
||||||
"recursively on all windows on this workspace.\n", con->name);
|
"recursively on all windows on this workspace.\n",
|
||||||
|
con->name);
|
||||||
Con *current;
|
Con *current;
|
||||||
current = TAILQ_FIRST(&(con->focus_head));
|
current = TAILQ_FIRST(&(con->focus_head));
|
||||||
while (current) {
|
while (current) {
|
||||||
@ -115,25 +116,25 @@ void scratchpad_show(Con *con) {
|
|||||||
* unfocused scratchpad on the current workspace and focus it */
|
* unfocused scratchpad on the current workspace and focus it */
|
||||||
Con *walk_con;
|
Con *walk_con;
|
||||||
Con *focused_ws = con_get_workspace(focused);
|
Con *focused_ws = con_get_workspace(focused);
|
||||||
TAILQ_FOREACH(walk_con, &(focused_ws->floating_head), floating_windows) {
|
TAILQ_FOREACH (walk_con, &(focused_ws->floating_head), floating_windows) {
|
||||||
if (!con && (floating = con_inside_floating(walk_con)) &&
|
if (!con && (floating = con_inside_floating(walk_con)) &&
|
||||||
floating->scratchpad_state != SCRATCHPAD_NONE &&
|
floating->scratchpad_state != SCRATCHPAD_NONE &&
|
||||||
floating != con_inside_floating(focused)) {
|
floating != con_inside_floating(focused)) {
|
||||||
DLOG("Found an unfocused scratchpad window on this workspace\n");
|
DLOG("Found an unfocused scratchpad window on this workspace\n");
|
||||||
DLOG("Focusing it: %p\n", walk_con);
|
DLOG("Focusing it: %p\n", walk_con);
|
||||||
/* use con_descend_tiling_focused to get the last focused
|
/* use con_descend_tiling_focused to get the last focused
|
||||||
* window inside this scratch container in order to
|
* window inside this scratch container in order to
|
||||||
* keep the focus the same within this container */
|
* keep the focus the same within this container */
|
||||||
con_focus(con_descend_tiling_focused(walk_con));
|
con_focus(con_descend_tiling_focused(walk_con));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this was 'scratchpad show' without criteria, we check if there is a
|
/* If this was 'scratchpad show' without criteria, we check if there is a
|
||||||
* visible scratchpad window on another workspace. In this case we move it
|
* visible scratchpad window on another workspace. In this case we move it
|
||||||
* to the current workspace. */
|
* to the current workspace. */
|
||||||
focused_ws = con_get_workspace(focused);
|
focused_ws = con_get_workspace(focused);
|
||||||
TAILQ_FOREACH(walk_con, &all_cons, all_cons) {
|
TAILQ_FOREACH (walk_con, &all_cons, all_cons) {
|
||||||
Con *walk_ws = con_get_workspace(walk_con);
|
Con *walk_ws = con_get_workspace(walk_con);
|
||||||
if (!con && walk_ws &&
|
if (!con && walk_ws &&
|
||||||
!con_is_internal(walk_ws) && focused_ws != walk_ws &&
|
!con_is_internal(walk_ws) && focused_ws != walk_ws &&
|
||||||
@ -256,7 +257,7 @@ void scratchpad_fix_resolution(void) {
|
|||||||
Con *output;
|
Con *output;
|
||||||
int new_width = -1,
|
int new_width = -1,
|
||||||
new_height = -1;
|
new_height = -1;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
if (output == __i3_output)
|
if (output == __i3_output)
|
||||||
continue;
|
continue;
|
||||||
DLOG("output %s's resolution: (%d, %d) %d x %d\n",
|
DLOG("output %s's resolution: (%d, %d) %d x %d\n",
|
||||||
@ -287,7 +288,7 @@ void scratchpad_fix_resolution(void) {
|
|||||||
|
|
||||||
DLOG("Fixing coordinates of scratchpad windows\n");
|
DLOG("Fixing coordinates of scratchpad windows\n");
|
||||||
Con *con;
|
Con *con;
|
||||||
TAILQ_FOREACH(con, &(__i3_scratch->floating_head), floating_windows) {
|
TAILQ_FOREACH (con, &(__i3_scratch->floating_head), floating_windows) {
|
||||||
floating_fix_coordinates(con, &old_rect, &new_rect);
|
floating_fix_coordinates(con, &old_rect, &new_rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
537
src/sd-daemon.c
537
src/sd-daemon.c
@ -45,392 +45,387 @@
|
|||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
|
|
||||||
int sd_listen_fds(int unset_environment) {
|
int sd_listen_fds(int unset_environment) {
|
||||||
|
|
||||||
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
int r, fd;
|
int r, fd;
|
||||||
const char *e;
|
const char *e;
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
unsigned long l;
|
unsigned long l;
|
||||||
|
|
||||||
if (!(e = getenv("LISTEN_PID"))) {
|
if (!(e = getenv("LISTEN_PID"))) {
|
||||||
r = 0;
|
r = 0;
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
l = strtoul(e, &p, 10);
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
r = -errno;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p || *p || l <= 0) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this for us? */
|
||||||
|
if (getpid() != (pid_t)l) {
|
||||||
|
r = 0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(e = getenv("LISTEN_FDS"))) {
|
||||||
|
r = 0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
l = strtoul(e, &p, 10);
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
r = -errno;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p || *p) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int)l; fd++) {
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
if ((flags = fcntl(fd, F_GETFD)) < 0) {
|
||||||
|
r = -errno;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
if (flags & FD_CLOEXEC)
|
||||||
l = strtoul(e, &p, 10);
|
continue;
|
||||||
|
|
||||||
if (errno != 0) {
|
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!p || *p || l <= 0) {
|
r = (int)l;
|
||||||
r = -EINVAL;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this for us? */
|
|
||||||
if (getpid() != (pid_t) l) {
|
|
||||||
r = 0;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(e = getenv("LISTEN_FDS"))) {
|
|
||||||
r = 0;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
l = strtoul(e, &p, 10);
|
|
||||||
|
|
||||||
if (errno != 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p || *p) {
|
|
||||||
r = -EINVAL;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
if ((flags = fcntl(fd, F_GETFD)) < 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & FD_CLOEXEC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (int) l;
|
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (unset_environment) {
|
if (unset_environment) {
|
||||||
unsetenv("LISTEN_PID");
|
unsetenv("LISTEN_PID");
|
||||||
unsetenv("LISTEN_FDS");
|
unsetenv("LISTEN_FDS");
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_is_fifo(int fd, const char *path) {
|
int sd_is_fifo(int fd, const char *path) {
|
||||||
struct stat st_fd;
|
struct stat st_fd;
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(&st_fd, 0, sizeof(st_fd));
|
memset(&st_fd, 0, sizeof(st_fd));
|
||||||
if (fstat(fd, &st_fd) < 0)
|
if (fstat(fd, &st_fd) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (!S_ISFIFO(st_fd.st_mode))
|
if (!S_ISFIFO(st_fd.st_mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
struct stat st_path;
|
||||||
|
|
||||||
|
memset(&st_path, 0, sizeof(st_path));
|
||||||
|
if (stat(path, &st_path) < 0) {
|
||||||
|
if (errno == ENOENT || errno == ENOTDIR)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (path) {
|
return -errno;
|
||||||
struct stat st_path;
|
|
||||||
|
|
||||||
memset(&st_path, 0, sizeof(st_path));
|
|
||||||
if (stat(path, &st_path) < 0) {
|
|
||||||
|
|
||||||
if (errno == ENOENT || errno == ENOTDIR)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
st_path.st_dev == st_fd.st_dev &&
|
|
||||||
st_path.st_ino == st_fd.st_ino;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return st_path.st_dev == st_fd.st_dev &&
|
||||||
|
st_path.st_ino == st_fd.st_ino;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sd_is_socket_internal(int fd, int type, int listening) {
|
static int sd_is_socket_internal(int fd, int type, int listening) {
|
||||||
struct stat st_fd;
|
struct stat st_fd;
|
||||||
|
|
||||||
if (fd < 0 || type < 0)
|
if (fd < 0 || type < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (fstat(fd, &st_fd) < 0)
|
if (fstat(fd, &st_fd) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (!S_ISSOCK(st_fd.st_mode))
|
if (!S_ISSOCK(st_fd.st_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (type != 0) {
|
if (type != 0) {
|
||||||
int other_type = 0;
|
int other_type = 0;
|
||||||
socklen_t l = sizeof(other_type);
|
socklen_t l = sizeof(other_type);
|
||||||
|
|
||||||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
|
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (l != sizeof(other_type))
|
if (l != sizeof(other_type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (other_type != type)
|
if (other_type != type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listening >= 0) {
|
if (listening >= 0) {
|
||||||
int accepting = 0;
|
int accepting = 0;
|
||||||
socklen_t l = sizeof(accepting);
|
socklen_t l = sizeof(accepting);
|
||||||
|
|
||||||
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
|
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (l != sizeof(accepting))
|
if (l != sizeof(accepting))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!accepting != !listening)
|
if (!accepting != !listening)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
struct sockaddr_in in4;
|
struct sockaddr_in in4;
|
||||||
struct sockaddr_in6 in6;
|
struct sockaddr_in6 in6;
|
||||||
struct sockaddr_un un;
|
struct sockaddr_un un;
|
||||||
struct sockaddr_storage storage;
|
struct sockaddr_storage storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
int sd_is_socket(int fd, int family, int type, int listening) {
|
int sd_is_socket(int fd, int family, int type, int listening) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (family < 0)
|
if (family < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (family > 0) {
|
if (family > 0) {
|
||||||
union sockaddr_union sockaddr;
|
union sockaddr_union sockaddr;
|
||||||
socklen_t l;
|
socklen_t l;
|
||||||
|
|
||||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
l = sizeof(sockaddr);
|
l = sizeof(sockaddr);
|
||||||
|
|
||||||
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (l < sizeof(sa_family_t))
|
if (l < sizeof(sa_family_t))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return sockaddr.sa.sa_family == family;
|
return sockaddr.sa.sa_family == family;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
|
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
|
||||||
union sockaddr_union sockaddr;
|
union sockaddr_union sockaddr;
|
||||||
socklen_t l;
|
socklen_t l;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (family != 0 && family != AF_INET && family != AF_INET6)
|
if (family != 0 && family != AF_INET && family != AF_INET6)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
|
l = sizeof(sockaddr);
|
||||||
|
|
||||||
|
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (l < sizeof(sa_family_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (sockaddr.sa.sa_family != AF_INET &&
|
||||||
|
sockaddr.sa.sa_family != AF_INET6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (family > 0)
|
||||||
|
if (sockaddr.sa.sa_family != family)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (port > 0) {
|
||||||
|
if (sockaddr.sa.sa_family == AF_INET) {
|
||||||
|
if (l < sizeof(struct sockaddr_in))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
return htons(port) == sockaddr.in4.sin_port;
|
||||||
return r;
|
} else {
|
||||||
|
if (l < sizeof(struct sockaddr_in6))
|
||||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
|
||||||
l = sizeof(sockaddr);
|
|
||||||
|
|
||||||
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (l < sizeof(sa_family_t))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (sockaddr.sa.sa_family != AF_INET &&
|
return htons(port) == sockaddr.in6.sin6_port;
|
||||||
sockaddr.sa.sa_family != AF_INET6)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (family > 0)
|
|
||||||
if (sockaddr.sa.sa_family != family)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (port > 0) {
|
|
||||||
if (sockaddr.sa.sa_family == AF_INET) {
|
|
||||||
if (l < sizeof(struct sockaddr_in))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return htons(port) == sockaddr.in4.sin_port;
|
|
||||||
} else {
|
|
||||||
if (l < sizeof(struct sockaddr_in6))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return htons(port) == sockaddr.in6.sin6_port;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
|
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
|
||||||
union sockaddr_union sockaddr;
|
union sockaddr_union sockaddr;
|
||||||
socklen_t l;
|
socklen_t l;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
l = sizeof(sockaddr);
|
l = sizeof(sockaddr);
|
||||||
|
|
||||||
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
if (getsockname(fd, &sockaddr.sa, &l) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (l < sizeof(sa_family_t))
|
if (l < sizeof(sa_family_t))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (sockaddr.sa.sa_family != AF_UNIX)
|
if (sockaddr.sa.sa_family != AF_UNIX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
length = strlen(path);
|
length = strlen(path);
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
/* Unnamed socket */
|
/* Unnamed socket */
|
||||||
return l == offsetof(struct sockaddr_un, sun_path);
|
return l == offsetof(struct sockaddr_un, sun_path);
|
||||||
|
|
||||||
if (path[0])
|
if (path[0])
|
||||||
/* Normal path socket */
|
/* Normal path socket */
|
||||||
return
|
return (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
|
||||||
(l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
|
memcmp(path, sockaddr.un.sun_path, length + 1) == 0;
|
||||||
memcmp(path, sockaddr.un.sun_path, length+1) == 0;
|
else
|
||||||
else
|
/* Abstract namespace socket */
|
||||||
/* Abstract namespace socket */
|
return (l == offsetof(struct sockaddr_un, sun_path) + length) &&
|
||||||
return
|
memcmp(path, sockaddr.un.sun_path, length) == 0;
|
||||||
(l == offsetof(struct sockaddr_un, sun_path) + length) &&
|
}
|
||||||
memcmp(path, sockaddr.un.sun_path, length) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_notify(int unset_environment, const char *state) {
|
int sd_notify(int unset_environment, const char *state) {
|
||||||
#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
|
#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
int fd = -1, r;
|
int fd = -1, r;
|
||||||
struct msghdr msghdr;
|
struct msghdr msghdr;
|
||||||
struct iovec iovec;
|
struct iovec iovec;
|
||||||
union sockaddr_union sockaddr;
|
union sockaddr_union sockaddr;
|
||||||
const char *e;
|
const char *e;
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(e = getenv("NOTIFY_SOCKET")))
|
if (!(e = getenv("NOTIFY_SOCKET")))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Must be an abstract socket, or an absolute path */
|
/* Must be an abstract socket, or an absolute path */
|
||||||
if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
|
if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
|
if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
sockaddr.sa.sa_family = AF_UNIX;
|
sockaddr.sa.sa_family = AF_UNIX;
|
||||||
strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
|
strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
|
||||||
|
|
||||||
if (sockaddr.un.sun_path[0] == '@')
|
if (sockaddr.un.sun_path[0] == '@')
|
||||||
sockaddr.un.sun_path[0] = 0;
|
sockaddr.un.sun_path[0] = 0;
|
||||||
|
|
||||||
memset(&iovec, 0, sizeof(iovec));
|
memset(&iovec, 0, sizeof(iovec));
|
||||||
iovec.iov_base = (char*) state;
|
iovec.iov_base = (char *)state;
|
||||||
iovec.iov_len = strlen(state);
|
iovec.iov_len = strlen(state);
|
||||||
|
|
||||||
memset(&msghdr, 0, sizeof(msghdr));
|
memset(&msghdr, 0, sizeof(msghdr));
|
||||||
msghdr.msg_name = &sockaddr;
|
msghdr.msg_name = &sockaddr;
|
||||||
msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
|
msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
|
||||||
|
|
||||||
if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
|
if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
|
||||||
msghdr.msg_namelen = sizeof(struct sockaddr_un);
|
msghdr.msg_namelen = sizeof(struct sockaddr_un);
|
||||||
|
|
||||||
msghdr.msg_iov = &iovec;
|
msghdr.msg_iov = &iovec;
|
||||||
msghdr.msg_iovlen = 1;
|
msghdr.msg_iovlen = 1;
|
||||||
|
|
||||||
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
|
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (unset_environment)
|
if (unset_environment)
|
||||||
unsetenv("NOTIFY_SOCKET");
|
unsetenv("NOTIFY_SOCKET");
|
||||||
|
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_notifyf(int unset_environment, const char *format, ...) {
|
int sd_notifyf(int unset_environment, const char *format, ...) {
|
||||||
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
r = vasprintf(&p, format, ap);
|
r = vasprintf(&p, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (r < 0 || !p)
|
if (r < 0 || !p)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = sd_notify(unset_environment, p);
|
r = sd_notify(unset_environment, p);
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_booted(void) {
|
int sd_booted(void) {
|
||||||
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct stat a, b;
|
struct stat a, b;
|
||||||
|
|
||||||
/* We simply test whether the systemd cgroup hierarchy is
|
/* We simply test whether the systemd cgroup hierarchy is
|
||||||
* mounted */
|
* mounted */
|
||||||
|
|
||||||
if (lstat("/sys/fs/cgroup", &a) < 0)
|
if (lstat("/sys/fs/cgroup", &a) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
|
if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return a.st_dev != b.st_dev;
|
return a.st_dev != b.st_dev;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,7 @@ static char *crash_text[] = {
|
|||||||
"or press",
|
"or press",
|
||||||
"- 'b' to save a backtrace (needs GDB),",
|
"- 'b' to save a backtrace (needs GDB),",
|
||||||
"- 'r' to restart i3 in-place or",
|
"- 'r' to restart i3 in-place or",
|
||||||
"- 'f' to forget the current layout and restart"
|
"- 'f' to forget the current layout and restart"};
|
||||||
};
|
|
||||||
static int crash_text_longest = 5;
|
static int crash_text_longest = 5;
|
||||||
static int backtrace_string_index = 3;
|
static int backtrace_string_index = 3;
|
||||||
static int backtrace_done = 0;
|
static int backtrace_done = 0;
|
||||||
@ -102,8 +101,7 @@ static int backtrace(void) {
|
|||||||
"-ex", "set logging on",
|
"-ex", "set logging on",
|
||||||
"-ex", "bt full",
|
"-ex", "bt full",
|
||||||
"-ex", "quit",
|
"-ex", "quit",
|
||||||
NULL
|
NULL};
|
||||||
};
|
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
DLOG("Failed to exec GDB\n");
|
DLOG("Failed to exec GDB\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -129,11 +127,11 @@ static int backtrace(void) {
|
|||||||
*/
|
*/
|
||||||
static int sig_draw_window(xcb_window_t win, int width, int height, int font_height, i3String **crash_text_i3strings) {
|
static int sig_draw_window(xcb_window_t win, int width, int height, int font_height, i3String **crash_text_i3strings) {
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_rectangle_t border = { 0, 0, width, height},
|
xcb_rectangle_t border = {0, 0, width, height},
|
||||||
inner = { 2, 2, width - 4, height - 4};
|
inner = {2, 2, width - 4, height - 4};
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#FF0000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#000000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
||||||
|
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
@ -151,7 +149,7 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei
|
|||||||
set_font_colors(pixmap_gc, get_colorpixel(bt_colour), get_colorpixel("#000000"));
|
set_font_colors(pixmap_gc, get_colorpixel(bt_colour), get_colorpixel("#000000"));
|
||||||
|
|
||||||
draw_text(crash_text_i3strings[i], pixmap, pixmap_gc,
|
draw_text(crash_text_i3strings[i], pixmap, pixmap_gc,
|
||||||
8, 5 + i * font_height, width - 16);
|
8, 5 + i * font_height, width - 16);
|
||||||
|
|
||||||
/* and reset the colour again for other lines */
|
/* and reset the colour again for other lines */
|
||||||
if (i == backtrace_string_index)
|
if (i == backtrace_string_index)
|
||||||
@ -221,10 +219,10 @@ static xcb_window_t open_input_window(xcb_connection_t *conn, Rect screen_rect,
|
|||||||
|
|
||||||
xcb_create_window(conn,
|
xcb_create_window(conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
x, y, width, height, /* dimensions */
|
x, y, width, height, /* dimensions */
|
||||||
0, /* border = 0, we draw our own */
|
0, /* border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
mask,
|
mask,
|
||||||
@ -238,10 +236,10 @@ static xcb_window_t open_input_window(xcb_connection_t *conn, Rect screen_rect,
|
|||||||
|
|
||||||
static void open_popups() {
|
static void open_popups() {
|
||||||
/* width and height of the popup window, so that the text fits in */
|
/* width and height of the popup window, so that the text fits in */
|
||||||
int crash_text_num = sizeof(crash_text) / sizeof(char*);
|
int crash_text_num = sizeof(crash_text) / sizeof(char *);
|
||||||
int height = 13 + (crash_text_num * config.font.height);
|
int height = 13 + (crash_text_num * config.font.height);
|
||||||
|
|
||||||
int crash_text_length = sizeof(crash_text) / sizeof(char*);
|
int crash_text_length = sizeof(crash_text) / sizeof(char *);
|
||||||
i3String **crash_text_i3strings = smalloc(sizeof(i3String *) * (crash_text_length + 1));
|
i3String **crash_text_i3strings = smalloc(sizeof(i3String *) * (crash_text_length + 1));
|
||||||
/* Pre-compute i3Strings for our text */
|
/* Pre-compute i3Strings for our text */
|
||||||
for (int i = 0; i < crash_text_length; ++i) {
|
for (int i = 0; i < crash_text_length; ++i) {
|
||||||
@ -255,7 +253,7 @@ static void open_popups() {
|
|||||||
/* Open a popup window on each virtual screen */
|
/* Open a popup window on each virtual screen */
|
||||||
Output *screen;
|
Output *screen;
|
||||||
xcb_window_t win;
|
xcb_window_t win;
|
||||||
TAILQ_FOREACH(screen, &outputs, outputs) {
|
TAILQ_FOREACH (screen, &outputs, outputs) {
|
||||||
if (!screen->active)
|
if (!screen->active)
|
||||||
continue;
|
continue;
|
||||||
win = open_input_window(conn, screen->rect, width, height);
|
win = open_input_window(conn, screen->rect, width, height);
|
||||||
@ -300,7 +298,7 @@ void handle_signal(int sig, siginfo_t *info, void *data) {
|
|||||||
/* Strip off the highest bit (set if the event is generated) */
|
/* Strip off the highest bit (set if the event is generated) */
|
||||||
int type = (event->response_type & 0x7F);
|
int type = (event->response_type & 0x7F);
|
||||||
if (type == XCB_KEY_PRESS) {
|
if (type == XCB_KEY_PRESS) {
|
||||||
sig_handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
|
sig_handle_key_press(NULL, conn, (xcb_key_press_event_t *)event);
|
||||||
}
|
}
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ static void startup_timeout(EV_P_ ev_timer *w, int revents) {
|
|||||||
DLOG("Timeout for startup sequence %s\n", id);
|
DLOG("Timeout for startup sequence %s\n", id);
|
||||||
|
|
||||||
struct Startup_Sequence *current, *sequence = NULL;
|
struct Startup_Sequence *current, *sequence = NULL;
|
||||||
TAILQ_FOREACH(current, &startup_sequences, sequences) {
|
TAILQ_FOREACH (current, &startup_sequences, sequences) {
|
||||||
if (strcmp(current->id, id) != 0)
|
if (strcmp(current->id, id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -77,8 +77,7 @@ static int _prune_startup_sequences(void) {
|
|||||||
* seconds ago or earlier. */
|
* seconds ago or earlier. */
|
||||||
struct Startup_Sequence *current, *next;
|
struct Startup_Sequence *current, *next;
|
||||||
for (next = TAILQ_FIRST(&startup_sequences);
|
for (next = TAILQ_FIRST(&startup_sequences);
|
||||||
next != TAILQ_END(&startup_sequences);
|
next != TAILQ_END(&startup_sequences);) {
|
||||||
) {
|
|
||||||
current = next;
|
current = next;
|
||||||
next = TAILQ_NEXT(next, sequences);
|
next = TAILQ_NEXT(next, sequences);
|
||||||
|
|
||||||
@ -94,7 +93,6 @@ static int _prune_startup_sequences(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return active_sequences;
|
return active_sequences;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -193,7 +191,7 @@ void start_application(const char *command, bool no_startup_id) {
|
|||||||
if (!no_startup_id)
|
if (!no_startup_id)
|
||||||
sn_launcher_context_setup_child_process(context);
|
sn_launcher_context_setup_child_process(context);
|
||||||
|
|
||||||
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void*)NULL);
|
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void *)NULL);
|
||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
_exit(0);
|
_exit(0);
|
||||||
@ -204,7 +202,8 @@ void start_application(const char *command, bool no_startup_id) {
|
|||||||
/* Change the pointer of the root window to indicate progress */
|
/* Change the pointer of the root window to indicate progress */
|
||||||
if (xcursor_supported)
|
if (xcursor_supported)
|
||||||
xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
||||||
else xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
else
|
||||||
|
xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +219,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
|
|||||||
/* Get the corresponding internal startup sequence */
|
/* Get the corresponding internal startup sequence */
|
||||||
const char *id = sn_startup_sequence_get_id(snsequence);
|
const char *id = sn_startup_sequence_get_id(snsequence);
|
||||||
struct Startup_Sequence *current, *sequence = NULL;
|
struct Startup_Sequence *current, *sequence = NULL;
|
||||||
TAILQ_FOREACH(current, &startup_sequences, sequences) {
|
TAILQ_FOREACH (current, &startup_sequences, sequences) {
|
||||||
if (strcmp(current->id, id) != 0)
|
if (strcmp(current->id, id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -248,7 +247,8 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
|
|||||||
/* Change the pointer of the root window to indicate progress */
|
/* Change the pointer of the root window to indicate progress */
|
||||||
if (xcursor_supported)
|
if (xcursor_supported)
|
||||||
xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
||||||
else xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
else
|
||||||
|
xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -262,7 +262,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
|
struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
|
||||||
xcb_get_property_reply_t *startup_id_reply, bool ignore_mapped_leader) {
|
xcb_get_property_reply_t *startup_id_reply, bool ignore_mapped_leader) {
|
||||||
/* The _NET_STARTUP_ID is only needed during this function, so we get it
|
/* The _NET_STARTUP_ID is only needed during this function, so we get it
|
||||||
* here and don’t save it in the 'cwindow'. */
|
* here and don’t save it in the 'cwindow'. */
|
||||||
if (startup_id_reply == NULL || xcb_get_property_value_length(startup_id_reply) == 0) {
|
if (startup_id_reply == NULL || xcb_get_property_value_length(startup_id_reply) == 0) {
|
||||||
@ -288,7 +288,7 @@ struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
|
|||||||
xcb_get_property_cookie_t cookie;
|
xcb_get_property_cookie_t cookie;
|
||||||
|
|
||||||
cookie = xcb_get_property(conn, false, cwindow->leader,
|
cookie = xcb_get_property(conn, false, cwindow->leader,
|
||||||
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
|
||||||
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
|
||||||
|
|
||||||
if (startup_id_reply == NULL ||
|
if (startup_id_reply == NULL ||
|
||||||
@ -301,7 +301,7 @@ struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
|
|||||||
|
|
||||||
char *startup_id;
|
char *startup_id;
|
||||||
if (asprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
|
if (asprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
|
||||||
(char*)xcb_get_property_value(startup_id_reply)) == -1) {
|
(char *)xcb_get_property_value(startup_id_reply)) == -1) {
|
||||||
perror("asprintf()");
|
perror("asprintf()");
|
||||||
DLOG("Could not get _NET_STARTUP_ID\n");
|
DLOG("Could not get _NET_STARTUP_ID\n");
|
||||||
free(startup_id_reply);
|
free(startup_id_reply);
|
||||||
@ -309,7 +309,7 @@ struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Startup_Sequence *current, *sequence = NULL;
|
struct Startup_Sequence *current, *sequence = NULL;
|
||||||
TAILQ_FOREACH(current, &startup_sequences, sequences) {
|
TAILQ_FOREACH (current, &startup_sequences, sequences) {
|
||||||
if (strcmp(current->id, startup_id) != 0)
|
if (strcmp(current->id, startup_id) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
50
src/tree.c
50
src/tree.c
@ -76,12 +76,11 @@ bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) {
|
|||||||
|
|
||||||
/* TODO: refactor the following */
|
/* TODO: refactor the following */
|
||||||
croot = con_new(NULL, NULL);
|
croot = con_new(NULL, NULL);
|
||||||
croot->rect = (Rect){
|
croot->rect = (Rect) {
|
||||||
geometry->x,
|
geometry->x,
|
||||||
geometry->y,
|
geometry->y,
|
||||||
geometry->width,
|
geometry->width,
|
||||||
geometry->height
|
geometry->height};
|
||||||
};
|
|
||||||
focused = croot;
|
focused = croot;
|
||||||
|
|
||||||
tree_append_json(focused, globbed, NULL);
|
tree_append_json(focused, globbed, NULL);
|
||||||
@ -119,12 +118,11 @@ void tree_init(xcb_get_geometry_reply_t *geometry) {
|
|||||||
croot->name = "root";
|
croot->name = "root";
|
||||||
croot->type = CT_ROOT;
|
croot->type = CT_ROOT;
|
||||||
croot->layout = L_SPLITH;
|
croot->layout = L_SPLITH;
|
||||||
croot->rect = (Rect){
|
croot->rect = (Rect) {
|
||||||
geometry->x,
|
geometry->x,
|
||||||
geometry->y,
|
geometry->y,
|
||||||
geometry->width,
|
geometry->width,
|
||||||
geometry->height
|
geometry->height};
|
||||||
};
|
|
||||||
|
|
||||||
_create___i3();
|
_create___i3();
|
||||||
}
|
}
|
||||||
@ -169,7 +167,7 @@ Con *tree_open_con(Con *con, i3Window *window) {
|
|||||||
static bool _is_con_mapped(Con *con) {
|
static bool _is_con_mapped(Con *con) {
|
||||||
Con *child;
|
Con *child;
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
if (_is_con_mapped(child))
|
if (_is_con_mapped(child))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -216,7 +214,7 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
|
|||||||
bool abort_kill = false;
|
bool abort_kill = false;
|
||||||
/* We cannot use TAILQ_FOREACH because the children get deleted
|
/* We cannot use TAILQ_FOREACH because the children get deleted
|
||||||
* in their parent’s nodes_head */
|
* in their parent’s nodes_head */
|
||||||
for (child = TAILQ_FIRST(&(con->nodes_head)); child; ) {
|
for (child = TAILQ_FIRST(&(con->nodes_head)); child;) {
|
||||||
nextchild = TAILQ_NEXT(child, nodes);
|
nextchild = TAILQ_NEXT(child, nodes);
|
||||||
DLOG("killing child=%p\n", child);
|
DLOG("killing child=%p\n", child);
|
||||||
if (!tree_close(child, kill_window, true, false))
|
if (!tree_close(child, kill_window, true, false))
|
||||||
@ -239,7 +237,7 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
|
|||||||
* unmap the window,
|
* unmap the window,
|
||||||
* then reparent it to the root window. */
|
* then reparent it to the root window. */
|
||||||
xcb_change_window_attributes(conn, con->window->id,
|
xcb_change_window_attributes(conn, con->window->id,
|
||||||
XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_NONE });
|
XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_NONE});
|
||||||
xcb_unmap_window(conn, con->window->id);
|
xcb_unmap_window(conn, con->window->id);
|
||||||
cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0);
|
cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0);
|
||||||
|
|
||||||
@ -249,9 +247,9 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
|
|||||||
|
|
||||||
/* We are no longer handling this window, thus set WM_STATE to
|
/* We are no longer handling this window, thus set WM_STATE to
|
||||||
* WM_STATE_WITHDRAWN (see ICCCM 4.1.3.1) */
|
* WM_STATE_WITHDRAWN (see ICCCM 4.1.3.1) */
|
||||||
long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
|
long data[] = {XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE};
|
||||||
cookie = xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
|
cookie = xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
|
||||||
con->window->id, A_WM_STATE, A_WM_STATE, 32, 2, data);
|
con->window->id, A_WM_STATE, A_WM_STATE, 32, 2, data);
|
||||||
|
|
||||||
/* Ignore X11 errors for the ReparentWindow request.
|
/* Ignore X11 errors for the ReparentWindow request.
|
||||||
* X11 Errors are returned when the window was already destroyed */
|
* X11 Errors are returned when the window was already destroyed */
|
||||||
@ -337,10 +335,10 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
|
|||||||
} else {
|
} else {
|
||||||
if (!force_set_focus && con != focused)
|
if (!force_set_focus && con != focused)
|
||||||
DLOG("not changing focus, the container was not focused before\n");
|
DLOG("not changing focus, the container was not focused before\n");
|
||||||
else con_focus(next);
|
else
|
||||||
|
con_focus(next);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
DLOG("not focusing because we're not killing anybody\n");
|
DLOG("not focusing because we're not killing anybody\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -368,7 +366,7 @@ void tree_close_con(kill_window_t kill_window) {
|
|||||||
if (focused->type == CT_WORKSPACE) {
|
if (focused->type == CT_WORKSPACE) {
|
||||||
DLOG("Workspaces cannot be close, closing all children instead\n");
|
DLOG("Workspaces cannot be close, closing all children instead\n");
|
||||||
Con *child, *nextchild;
|
Con *child, *nextchild;
|
||||||
for (child = TAILQ_FIRST(&(focused->focus_head)); child; ) {
|
for (child = TAILQ_FIRST(&(focused->focus_head)); child;) {
|
||||||
nextchild = TAILQ_NEXT(child, focused);
|
nextchild = TAILQ_NEXT(child, focused);
|
||||||
DLOG("killing child=%p\n", child);
|
DLOG("killing child=%p\n", child);
|
||||||
tree_close(child, kill_window, false, false);
|
tree_close(child, kill_window, false, false);
|
||||||
@ -472,16 +470,14 @@ bool level_down(void) {
|
|||||||
if (next == TAILQ_END(&(focused->focus_head))) {
|
if (next == TAILQ_END(&(focused->focus_head))) {
|
||||||
DLOG("cannot go down\n");
|
DLOG("cannot go down\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (next->type == CT_FLOATING_CON) {
|
||||||
else if (next->type == CT_FLOATING_CON) {
|
|
||||||
/* Floating cons shouldn't be directly focused; try immediately
|
/* Floating cons shouldn't be directly focused; try immediately
|
||||||
* going to the grandchild of the focused con. */
|
* going to the grandchild of the focused con. */
|
||||||
Con *child = TAILQ_FIRST(&(next->focus_head));
|
Con *child = TAILQ_FIRST(&(next->focus_head));
|
||||||
if (child == TAILQ_END(&(next->focus_head))) {
|
if (child == TAILQ_END(&(next->focus_head))) {
|
||||||
DLOG("cannot go down\n");
|
DLOG("cannot go down\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
next = TAILQ_FIRST(&(next->focus_head));
|
next = TAILQ_FIRST(&(next->focus_head));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,12 +489,12 @@ static void mark_unmapped(Con *con) {
|
|||||||
Con *current;
|
Con *current;
|
||||||
|
|
||||||
con->mapped = false;
|
con->mapped = false;
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes)
|
||||||
mark_unmapped(current);
|
mark_unmapped(current);
|
||||||
if (con->type == CT_WORKSPACE) {
|
if (con->type == CT_WORKSPACE) {
|
||||||
/* We need to call mark_unmapped on floating nodes aswell since we can
|
/* We need to call mark_unmapped on floating nodes aswell since we can
|
||||||
* make containers floating. */
|
* make containers floating. */
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
TAILQ_FOREACH (current, &(con->floating_head), floating_windows)
|
||||||
mark_unmapped(current);
|
mark_unmapped(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,13 +596,15 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
|
|||||||
Con *next;
|
Con *next;
|
||||||
if (way == 'n')
|
if (way == 'n')
|
||||||
next = TAILQ_NEXT(con, floating_windows);
|
next = TAILQ_NEXT(con, floating_windows);
|
||||||
else next = TAILQ_PREV(con, floating_head, floating_windows);
|
else
|
||||||
|
next = TAILQ_PREV(con, floating_head, floating_windows);
|
||||||
|
|
||||||
/* If there is no next/previous container, wrap */
|
/* If there is no next/previous container, wrap */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
if (way == 'n')
|
if (way == 'n')
|
||||||
next = TAILQ_FIRST(&(parent->floating_head));
|
next = TAILQ_FIRST(&(parent->floating_head));
|
||||||
else next = TAILQ_LAST(&(parent->floating_head), floating_head);
|
else
|
||||||
|
next = TAILQ_LAST(&(parent->floating_head), floating_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Still no next/previous container? bail out */
|
/* Still no next/previous container? bail out */
|
||||||
@ -639,7 +637,8 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
|
|||||||
Con *next;
|
Con *next;
|
||||||
if (way == 'n')
|
if (way == 'n')
|
||||||
next = TAILQ_NEXT(current, nodes);
|
next = TAILQ_NEXT(current, nodes);
|
||||||
else next = TAILQ_PREV(current, nodes_head, nodes);
|
else
|
||||||
|
next = TAILQ_PREV(current, nodes_head, nodes);
|
||||||
|
|
||||||
if (!next) {
|
if (!next) {
|
||||||
if (!config.force_focus_wrapping) {
|
if (!config.force_focus_wrapping) {
|
||||||
@ -655,7 +654,8 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
|
|||||||
|
|
||||||
if (way == 'n')
|
if (way == 'n')
|
||||||
next = TAILQ_FIRST(&(parent->nodes_head));
|
next = TAILQ_FIRST(&(parent->nodes_head));
|
||||||
else next = TAILQ_LAST(&(parent->nodes_head), nodes_head);
|
else
|
||||||
|
next = TAILQ_LAST(&(parent->nodes_head), nodes_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't violate fullscreen focus restrictions. */
|
/* Don't violate fullscreen focus restrictions. */
|
||||||
|
89
src/util.c
89
src/util.c
@ -42,24 +42,24 @@ bool rect_contains(Rect rect, uint32_t x, uint32_t y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rect rect_add(Rect a, Rect b) {
|
Rect rect_add(Rect a, Rect b) {
|
||||||
return (Rect){a.x + b.x,
|
return (Rect) {a.x + b.x,
|
||||||
a.y + b.y,
|
a.y + b.y,
|
||||||
a.width + b.width,
|
a.width + b.width,
|
||||||
a.height + b.height};
|
a.height + b.height};
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect rect_sub(Rect a, Rect b) {
|
Rect rect_sub(Rect a, Rect b) {
|
||||||
return (Rect){a.x - b.x,
|
return (Rect) {a.x - b.x,
|
||||||
a.y - b.y,
|
a.y - b.y,
|
||||||
a.width - b.width,
|
a.width - b.width,
|
||||||
a.height - b.height};
|
a.height - b.height};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the name consists of only digits.
|
* Returns true if the name consists of only digits.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
__attribute__ ((pure)) bool name_is_digits(const char *name) {
|
__attribute__((pure)) bool name_is_digits(const char *name) {
|
||||||
/* positive integers and zero are interpreted as numbers */
|
/* positive integers and zero are interpreted as numbers */
|
||||||
for (size_t i = 0; i < strlen(name); i++)
|
for (size_t i = 0; i < strlen(name); i++)
|
||||||
if (!isdigit(name[i]))
|
if (!isdigit(name[i]))
|
||||||
@ -78,9 +78,9 @@ long ws_name_to_number(const char *name) {
|
|||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
long parsed_num = strtol(name, &endptr, 10);
|
long parsed_num = strtol(name, &endptr, 10);
|
||||||
if (parsed_num == LONG_MIN ||
|
if (parsed_num == LONG_MIN ||
|
||||||
parsed_num == LONG_MAX ||
|
parsed_num == LONG_MAX ||
|
||||||
parsed_num < 0 ||
|
parsed_num < 0 ||
|
||||||
endptr == name) {
|
endptr == name) {
|
||||||
parsed_num = -1;
|
parsed_num = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ void exec_i3_utility(char *name, char *argv[]) {
|
|||||||
void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_message) {
|
void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_message) {
|
||||||
xcb_generic_error_t *error = xcb_request_check(conn, cookie);
|
xcb_generic_error_t *error = xcb_request_check(conn, cookie);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
fprintf(stderr, "ERROR: %s (X error %d)\n", err_message , error->error_code);
|
fprintf(stderr, "ERROR: %s (X error %d)\n", err_message, error->error_code);
|
||||||
xcb_disconnect(conn);
|
xcb_disconnect(conn);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
@ -166,29 +166,29 @@ void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_mes
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *resolve_tilde(const char *path) {
|
char *resolve_tilde(const char *path) {
|
||||||
static glob_t globbuf;
|
static glob_t globbuf;
|
||||||
char *head, *tail, *result;
|
char *head, *tail, *result;
|
||||||
|
|
||||||
tail = strchr(path, '/');
|
tail = strchr(path, '/');
|
||||||
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));
|
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));
|
||||||
|
|
||||||
int res = glob(head, GLOB_TILDE, NULL, &globbuf);
|
int res = glob(head, GLOB_TILDE, NULL, &globbuf);
|
||||||
free(head);
|
free(head);
|
||||||
/* no match, or many wildcard matches are bad */
|
/* no match, or many wildcard matches are bad */
|
||||||
if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
|
if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
|
||||||
result = sstrdup(path);
|
result = sstrdup(path);
|
||||||
else if (res != 0) {
|
else if (res != 0) {
|
||||||
die("glob() failed");
|
die("glob() failed");
|
||||||
} else {
|
} else {
|
||||||
head = globbuf.gl_pathv[0];
|
head = globbuf.gl_pathv[0];
|
||||||
result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
|
result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
|
||||||
strncpy(result, head, strlen(head));
|
strncpy(result, head, strlen(head));
|
||||||
if (tail)
|
if (tail)
|
||||||
strncat(result, tail, strlen(tail));
|
strncat(result, tail, strlen(tail));
|
||||||
}
|
}
|
||||||
globfree(&globbuf);
|
globfree(&globbuf);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -196,8 +196,8 @@ char *resolve_tilde(const char *path) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool path_exists(const char *path) {
|
bool path_exists(const char *path) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
return (stat(path, &buf) == 0);
|
return (stat(path, &buf) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -215,16 +215,16 @@ static char **append_argument(char **original, char *argument) {
|
|||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
/* Copy the original array */
|
/* Copy the original array */
|
||||||
char **result = smalloc((num_args+2) * sizeof(char*));
|
char **result = smalloc((num_args + 2) * sizeof(char *));
|
||||||
memcpy(result, original, num_args * sizeof(char*));
|
memcpy(result, original, num_args * sizeof(char *));
|
||||||
result[num_args] = argument;
|
result[num_args] = argument;
|
||||||
result[num_args+1] = NULL;
|
result[num_args + 1] = NULL;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define y(x, ...) yajl_gen_ ## x (gen, ##__VA_ARGS__)
|
#define y(x, ...) yajl_gen_##x(gen, ##__VA_ARGS__)
|
||||||
#define ystr(str) yajl_gen_string(gen, (unsigned char*)str, strlen(str))
|
#define ystr(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
|
||||||
|
|
||||||
char *store_restart_layout(void) {
|
char *store_restart_layout(void) {
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
@ -309,8 +309,9 @@ void i3_restart(bool forget_layout) {
|
|||||||
if (restart_filename != NULL) {
|
if (restart_filename != NULL) {
|
||||||
/* create the new argv */
|
/* create the new argv */
|
||||||
int num_args;
|
int num_args;
|
||||||
for (num_args = 0; start_argv[num_args] != NULL; num_args++);
|
for (num_args = 0; start_argv[num_args] != NULL; num_args++)
|
||||||
char **new_argv = scalloc((num_args + 3) * sizeof(char*));
|
;
|
||||||
|
char **new_argv = scalloc((num_args + 3) * sizeof(char *));
|
||||||
|
|
||||||
/* copy the arguments, but skip the ones we'll replace */
|
/* copy the arguments, but skip the ones we'll replace */
|
||||||
int write_index = 0;
|
int write_index = 0;
|
||||||
@ -392,7 +393,7 @@ static void nagbar_exited(EV_P_ ev_child *watcher, int revents) {
|
|||||||
ELOG("ERROR: i3-nagbar could not be found. Is it correctly installed on your system?\n");
|
ELOG("ERROR: i3-nagbar could not be found. Is it correctly installed on your system?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
*((pid_t*)watcher->data) = -1;
|
*((pid_t *)watcher->data) = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -401,7 +402,7 @@ static void nagbar_exited(EV_P_ ev_child *watcher, int revents) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) {
|
static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) {
|
||||||
pid_t *nagbar_pid = (pid_t*)watcher->data;
|
pid_t *nagbar_pid = (pid_t *)watcher->data;
|
||||||
if (*nagbar_pid != -1) {
|
if (*nagbar_pid != -1) {
|
||||||
LOG("Sending SIGKILL (%d) to i3-nagbar with PID %d\n", SIGKILL, *nagbar_pid);
|
LOG("Sending SIGKILL (%d) to i3-nagbar with PID %d\n", SIGKILL, *nagbar_pid);
|
||||||
kill(*nagbar_pid, SIGKILL);
|
kill(*nagbar_pid, SIGKILL);
|
||||||
|
17
src/window.c
17
src/window.c
@ -34,7 +34,8 @@ void window_update_class(i3Window *win, xcb_get_property_reply_t *prop, bool bef
|
|||||||
win->class_instance = sstrdup(new_class);
|
win->class_instance = sstrdup(new_class);
|
||||||
if ((strlen(new_class) + 1) < (size_t)xcb_get_property_value_length(prop))
|
if ((strlen(new_class) + 1) < (size_t)xcb_get_property_value_length(prop))
|
||||||
win->class_class = sstrdup(new_class + strlen(new_class) + 1);
|
win->class_class = sstrdup(new_class + strlen(new_class) + 1);
|
||||||
else win->class_class = NULL;
|
else
|
||||||
|
win->class_class = NULL;
|
||||||
LOG("WM_CLASS changed to %s (instance), %s (class)\n",
|
LOG("WM_CLASS changed to %s (instance), %s (class)\n",
|
||||||
win->class_instance, win->class_class);
|
win->class_instance, win->class_class);
|
||||||
|
|
||||||
@ -186,7 +187,7 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop)
|
|||||||
DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n",
|
DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n",
|
||||||
strut[0], strut[1], strut[2], strut[3]);
|
strut[0], strut[1], strut[2], strut[3]);
|
||||||
|
|
||||||
win->reserved = (struct reservedpx){ strut[0], strut[1], strut[2], strut[3] };
|
win->reserved = (struct reservedpx) {strut[0], strut[1], strut[2], strut[3]};
|
||||||
|
|
||||||
free(prop);
|
free(prop);
|
||||||
}
|
}
|
||||||
@ -204,7 +205,7 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo
|
|||||||
|
|
||||||
char *new_role;
|
char *new_role;
|
||||||
if (asprintf(&new_role, "%.*s", xcb_get_property_value_length(prop),
|
if (asprintf(&new_role, "%.*s", xcb_get_property_value_length(prop),
|
||||||
(char*)xcb_get_property_value(prop)) == -1) {
|
(char *)xcb_get_property_value(prop)) == -1) {
|
||||||
perror("asprintf()");
|
perror("asprintf()");
|
||||||
DLOG("Could not get WM_WINDOW_ROLE\n");
|
DLOG("Could not get WM_WINDOW_ROLE\n");
|
||||||
free(prop);
|
free(prop);
|
||||||
@ -268,16 +269,16 @@ void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *ur
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style) {
|
void window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style) {
|
||||||
/* This implementation simply mirrors Gnome's Metacity. Official
|
/* This implementation simply mirrors Gnome's Metacity. Official
|
||||||
* documentation of this hint is nowhere to be found.
|
* documentation of this hint is nowhere to be found.
|
||||||
* For more information see:
|
* For more information see:
|
||||||
* https://people.gnome.org/~tthurman/docs/metacity/xprops_8h-source.html
|
* https://people.gnome.org/~tthurman/docs/metacity/xprops_8h-source.html
|
||||||
* http://stackoverflow.com/questions/13787553/detect-if-a-x11-window-has-decorations
|
* http://stackoverflow.com/questions/13787553/detect-if-a-x11-window-has-decorations
|
||||||
*/
|
*/
|
||||||
#define MWM_HINTS_DECORATIONS (1 << 1)
|
#define MWM_HINTS_DECORATIONS (1 << 1)
|
||||||
#define MWM_DECOR_ALL (1 << 0)
|
#define MWM_DECOR_ALL (1 << 0)
|
||||||
#define MWM_DECOR_BORDER (1 << 1)
|
#define MWM_DECOR_BORDER (1 << 1)
|
||||||
#define MWM_DECOR_TITLE (1 << 3)
|
#define MWM_DECOR_TITLE (1 << 3)
|
||||||
|
|
||||||
if (motif_border_style != NULL)
|
if (motif_border_style != NULL)
|
||||||
*motif_border_style = BS_NORMAL;
|
*motif_border_style = BS_NORMAL;
|
||||||
|
104
src/workspace.c
104
src/workspace.c
@ -44,7 +44,7 @@ static void _workspace_apply_default_orientation(Con *ws) {
|
|||||||
Con *workspace_get(const char *num, bool *created) {
|
Con *workspace_get(const char *num, bool *created) {
|
||||||
Con *output, *workspace = NULL;
|
Con *output, *workspace = NULL;
|
||||||
|
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(workspace, output_get_content(output), !strcasecmp(child->name, num));
|
GREP_FIRST(workspace, output_get_content(output), !strcasecmp(child->name, num));
|
||||||
|
|
||||||
if (workspace == NULL) {
|
if (workspace == NULL) {
|
||||||
@ -59,14 +59,12 @@ Con *workspace_get(const char *num, bool *created) {
|
|||||||
* -1. */
|
* -1. */
|
||||||
long parsed_num = ws_name_to_number(num);
|
long parsed_num = ws_name_to_number(num);
|
||||||
|
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcmp(assignment->name, num) == 0) {
|
if (strcmp(assignment->name, num) == 0) {
|
||||||
DLOG("Found workspace name assignment to output \"%s\"\n", assignment->output);
|
DLOG("Found workspace name assignment to output \"%s\"\n", assignment->output);
|
||||||
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
||||||
break;
|
break;
|
||||||
} else if (parsed_num != -1
|
} else if (parsed_num != -1 && name_is_digits(assignment->name) && ws_name_to_number(assignment->name) == parsed_num) {
|
||||||
&& name_is_digits(assignment->name)
|
|
||||||
&& ws_name_to_number(assignment->name) == parsed_num) {
|
|
||||||
DLOG("Found workspace number assignment to output \"%s\"\n", assignment->output);
|
DLOG("Found workspace number assignment to output \"%s\"\n", assignment->output);
|
||||||
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
||||||
}
|
}
|
||||||
@ -96,8 +94,7 @@ Con *workspace_get(const char *num, bool *created) {
|
|||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
|
||||||
if (created != NULL)
|
if (created != NULL)
|
||||||
*created = true;
|
*created = true;
|
||||||
}
|
} else if (created != NULL) {
|
||||||
else if (created != NULL) {
|
|
||||||
*created = false;
|
*created = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,14 +117,14 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
|
|
||||||
/* try the configured workspace bindings first to find a free name */
|
/* try the configured workspace bindings first to find a free name */
|
||||||
Binding *bind;
|
Binding *bind;
|
||||||
TAILQ_FOREACH(bind, bindings, bindings) {
|
TAILQ_FOREACH (bind, bindings, bindings) {
|
||||||
DLOG("binding with command %s\n", bind->command);
|
DLOG("binding with command %s\n", bind->command);
|
||||||
if (strlen(bind->command) < strlen("workspace ") ||
|
if (strlen(bind->command) < strlen("workspace ") ||
|
||||||
strncasecmp(bind->command, "workspace", strlen("workspace")) != 0)
|
strncasecmp(bind->command, "workspace", strlen("workspace")) != 0)
|
||||||
continue;
|
continue;
|
||||||
DLOG("relevant command = %s\n", bind->command);
|
DLOG("relevant command = %s\n", bind->command);
|
||||||
char *target = bind->command + strlen("workspace ");
|
char *target = bind->command + strlen("workspace ");
|
||||||
while((*target == ' ' || *target == '\t') && target != '\0')
|
while ((*target == ' ' || *target == '\t') && target != '\0')
|
||||||
target++;
|
target++;
|
||||||
/* We check if this is the workspace
|
/* We check if this is the workspace
|
||||||
* next/prev/next_on_output/prev_on_output/back_and_forth/number command.
|
* next/prev/next_on_output/prev_on_output/back_and_forth/number command.
|
||||||
@ -150,8 +147,8 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
}
|
}
|
||||||
FREE(ws->name);
|
FREE(ws->name);
|
||||||
ws->name = strdup(target);
|
ws->name = strdup(target);
|
||||||
if (ws->name[strlen(ws->name)-1] == '"')
|
if (ws->name[strlen(ws->name) - 1] == '"')
|
||||||
ws->name[strlen(ws->name)-1] = '\0';
|
ws->name[strlen(ws->name) - 1] = '\0';
|
||||||
DLOG("trying name *%s*\n", ws->name);
|
DLOG("trying name *%s*\n", ws->name);
|
||||||
|
|
||||||
/* Ensure that this workspace is not assigned to a different output —
|
/* Ensure that this workspace is not assigned to a different output —
|
||||||
@ -159,7 +156,7 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
* find a new workspace, etc… */
|
* find a new workspace, etc… */
|
||||||
bool assigned = false;
|
bool assigned = false;
|
||||||
struct Workspace_Assignment *assignment;
|
struct Workspace_Assignment *assignment;
|
||||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
|
||||||
if (strcmp(assignment->name, ws->name) != 0 ||
|
if (strcmp(assignment->name, ws->name) != 0 ||
|
||||||
strcmp(assignment->output, output->name) == 0)
|
strcmp(assignment->output, output->name) == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -172,7 +169,7 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
current = NULL;
|
current = NULL;
|
||||||
TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (out, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(current, output_get_content(out), !strcasecmp(child->name, ws->name));
|
GREP_FIRST(current, output_get_content(out), !strcasecmp(child->name, ws->name));
|
||||||
|
|
||||||
exists = (current != NULL);
|
exists = (current != NULL);
|
||||||
@ -186,7 +183,8 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
parsed_num < 0 ||
|
parsed_num < 0 ||
|
||||||
endptr == ws->name)
|
endptr == ws->name)
|
||||||
ws->num = -1;
|
ws->num = -1;
|
||||||
else ws->num = parsed_num;
|
else
|
||||||
|
ws->num = parsed_num;
|
||||||
LOG("Used number %d for workspace with name %s\n", ws->num, ws->name);
|
LOG("Used number %d for workspace with name %s\n", ws->num, ws->name);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -203,7 +201,7 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
ws->num = c;
|
ws->num = c;
|
||||||
|
|
||||||
current = NULL;
|
current = NULL;
|
||||||
TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH (out, &(croot->nodes_head), nodes)
|
||||||
GREP_FIRST(current, output_get_content(out), child->num == ws->num);
|
GREP_FIRST(current, output_get_content(out), child->num == ws->num);
|
||||||
exists = (current != NULL);
|
exists = (current != NULL);
|
||||||
|
|
||||||
@ -225,7 +223,6 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
|||||||
return ws;
|
return ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the workspace is currently visible. Especially important for
|
* Returns true if the workspace is currently visible. Especially important for
|
||||||
* multi-monitor environments, as they can have multiple currenlty active
|
* multi-monitor environments, as they can have multiple currenlty active
|
||||||
@ -248,7 +245,7 @@ bool workspace_is_visible(Con *ws) {
|
|||||||
Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
|
Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
|
||||||
Con *current;
|
Con *current;
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
|
||||||
if (current != exclude &&
|
if (current != exclude &&
|
||||||
current->sticky_group != NULL &&
|
current->sticky_group != NULL &&
|
||||||
current->window != NULL &&
|
current->window != NULL &&
|
||||||
@ -260,7 +257,7 @@ Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
|
|||||||
return recurse;
|
return recurse;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows) {
|
TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
|
||||||
if (current != exclude &&
|
if (current != exclude &&
|
||||||
current->sticky_group != NULL &&
|
current->sticky_group != NULL &&
|
||||||
current->window != NULL &&
|
current->window != NULL &&
|
||||||
@ -287,7 +284,7 @@ static void workspace_reassign_sticky(Con *con) {
|
|||||||
/* 1: go through all containers */
|
/* 1: go through all containers */
|
||||||
|
|
||||||
/* handle all children and floating windows of this node */
|
/* handle all children and floating windows of this node */
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
|
||||||
if (current->sticky_group == NULL) {
|
if (current->sticky_group == NULL) {
|
||||||
workspace_reassign_sticky(current);
|
workspace_reassign_sticky(current);
|
||||||
continue;
|
continue;
|
||||||
@ -315,7 +312,7 @@ static void workspace_reassign_sticky(Con *con) {
|
|||||||
LOG("re-assigned window from src %p to dest %p\n", src, current);
|
LOG("re-assigned window from src %p to dest %p\n", src, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
TAILQ_FOREACH (current, &(con->floating_head), floating_windows)
|
||||||
workspace_reassign_sticky(current);
|
workspace_reassign_sticky(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,7 +344,7 @@ static void _workspace_show(Con *workspace) {
|
|||||||
|
|
||||||
/* disable fullscreen for the other workspaces and get the workspace we are
|
/* disable fullscreen for the other workspaces and get the workspace we are
|
||||||
* currently on. */
|
* currently on. */
|
||||||
TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(workspace->parent->nodes_head), nodes) {
|
||||||
if (current->fullscreen_mode == CF_OUTPUT)
|
if (current->fullscreen_mode == CF_OUTPUT)
|
||||||
old = current;
|
old = current;
|
||||||
current->fullscreen_mode = CF_NONE;
|
current->fullscreen_mode = CF_NONE;
|
||||||
@ -398,16 +395,16 @@ static void _workspace_show(Con *workspace) {
|
|||||||
|
|
||||||
if (focused->urgency_timer == NULL) {
|
if (focused->urgency_timer == NULL) {
|
||||||
DLOG("Deferring reset of urgency flag of con %p on newly shown workspace %p\n",
|
DLOG("Deferring reset of urgency flag of con %p on newly shown workspace %p\n",
|
||||||
focused, workspace);
|
focused, workspace);
|
||||||
focused->urgency_timer = scalloc(sizeof(struct ev_timer));
|
focused->urgency_timer = scalloc(sizeof(struct ev_timer));
|
||||||
/* use a repeating timer to allow for easy resets */
|
/* use a repeating timer to allow for easy resets */
|
||||||
ev_timer_init(focused->urgency_timer, workspace_defer_update_urgent_hint_cb,
|
ev_timer_init(focused->urgency_timer, workspace_defer_update_urgent_hint_cb,
|
||||||
config.workspace_urgency_timer, config.workspace_urgency_timer);
|
config.workspace_urgency_timer, config.workspace_urgency_timer);
|
||||||
focused->urgency_timer->data = focused;
|
focused->urgency_timer->data = focused;
|
||||||
ev_timer_start(main_loop, focused->urgency_timer);
|
ev_timer_start(main_loop, focused->urgency_timer);
|
||||||
} else {
|
} else {
|
||||||
DLOG("Resetting urgency timer of con %p on workspace %p\n",
|
DLOG("Resetting urgency timer of con %p on workspace %p\n",
|
||||||
focused, workspace);
|
focused, workspace);
|
||||||
ev_timer_again(main_loop, focused->urgency_timer);
|
ev_timer_again(main_loop, focused->urgency_timer);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -465,7 +462,7 @@ void workspace_show_by_name(const char *num) {
|
|||||||
* Focuses the next workspace.
|
* Focuses the next workspace.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con* workspace_next(void) {
|
Con *workspace_next(void) {
|
||||||
Con *current = con_get_workspace(focused);
|
Con *current = con_get_workspace(focused);
|
||||||
Con *next = NULL;
|
Con *next = NULL;
|
||||||
Con *output;
|
Con *output;
|
||||||
@ -475,11 +472,11 @@ Con* workspace_next(void) {
|
|||||||
next = TAILQ_NEXT(current, nodes);
|
next = TAILQ_NEXT(current, nodes);
|
||||||
} else {
|
} else {
|
||||||
/* If currently a numbered workspace, find next numbered workspace. */
|
/* If currently a numbered workspace, find next numbered workspace. */
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child->num == -1)
|
if (child->num == -1)
|
||||||
@ -496,11 +493,11 @@ Con* workspace_next(void) {
|
|||||||
/* Find next named workspace. */
|
/* Find next named workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child == current) {
|
if (child == current) {
|
||||||
@ -515,11 +512,11 @@ Con* workspace_next(void) {
|
|||||||
|
|
||||||
/* Find first workspace. */
|
/* Find first workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (!next || (child->num != -1 && child->num < next->num))
|
if (!next || (child->num != -1 && child->num < next->num))
|
||||||
@ -535,7 +532,7 @@ workspace_next_end:
|
|||||||
* Focuses the previous workspace.
|
* Focuses the previous workspace.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con* workspace_prev(void) {
|
Con *workspace_prev(void) {
|
||||||
Con *current = con_get_workspace(focused);
|
Con *current = con_get_workspace(focused);
|
||||||
Con *prev = NULL;
|
Con *prev = NULL;
|
||||||
Con *output;
|
Con *output;
|
||||||
@ -547,11 +544,11 @@ Con* workspace_prev(void) {
|
|||||||
prev = NULL;
|
prev = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* If numbered workspace, find previous numbered workspace. */
|
/* If numbered workspace, find previous numbered workspace. */
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
TAILQ_FOREACH_REVERSE (output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE || child->num == -1)
|
if (child->type != CT_WORKSPACE || child->num == -1)
|
||||||
continue;
|
continue;
|
||||||
/* Need to check child against current and previous because we
|
/* Need to check child against current and previous because we
|
||||||
@ -566,11 +563,11 @@ Con* workspace_prev(void) {
|
|||||||
/* Find previous named workspace. */
|
/* Find previous named workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
TAILQ_FOREACH_REVERSE (output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child == current) {
|
if (child == current) {
|
||||||
@ -585,11 +582,11 @@ Con* workspace_prev(void) {
|
|||||||
|
|
||||||
/* Find last workspace. */
|
/* Find last workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
TAILQ_FOREACH_REVERSE (output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
/* Skip outputs starting with __, they are internal. */
|
/* Skip outputs starting with __, they are internal. */
|
||||||
if (con_is_internal(output))
|
if (con_is_internal(output))
|
||||||
continue;
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (!prev || child->num > prev->num)
|
if (!prev || child->num > prev->num)
|
||||||
@ -602,22 +599,21 @@ workspace_prev_end:
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Focuses the next workspace on the same output.
|
* Focuses the next workspace on the same output.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con* workspace_next_on_output(void) {
|
Con *workspace_next_on_output(void) {
|
||||||
Con *current = con_get_workspace(focused);
|
Con *current = con_get_workspace(focused);
|
||||||
Con *next = NULL;
|
Con *next = NULL;
|
||||||
Con *output = con_get_output(focused);
|
Con *output = con_get_output(focused);
|
||||||
|
|
||||||
if (current->num == -1) {
|
if (current->num == -1) {
|
||||||
/* If currently a named workspace, find next named workspace. */
|
/* If currently a named workspace, find next named workspace. */
|
||||||
next = TAILQ_NEXT(current, nodes);
|
next = TAILQ_NEXT(current, nodes);
|
||||||
} else {
|
} else {
|
||||||
/* If currently a numbered workspace, find next numbered workspace. */
|
/* If currently a numbered workspace, find next numbered workspace. */
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child->num == -1)
|
if (child->num == -1)
|
||||||
@ -627,13 +623,13 @@ Con* workspace_next_on_output(void) {
|
|||||||
* relative order between the list of workspaces. */
|
* relative order between the list of workspaces. */
|
||||||
if (current->num < child->num && (!next || child->num < next->num))
|
if (current->num < child->num && (!next || child->num < next->num))
|
||||||
next = child;
|
next = child;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find next named workspace. */
|
/* Find next named workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child == current) {
|
if (child == current) {
|
||||||
@ -647,7 +643,7 @@ Con* workspace_next_on_output(void) {
|
|||||||
|
|
||||||
/* Find first workspace. */
|
/* Find first workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (!next || (child->num != -1 && child->num < next->num))
|
if (!next || (child->num != -1 && child->num < next->num))
|
||||||
@ -662,10 +658,10 @@ workspace_next_on_output_end:
|
|||||||
* Focuses the previous workspace on same output.
|
* Focuses the previous workspace on same output.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con* workspace_prev_on_output(void) {
|
Con *workspace_prev_on_output(void) {
|
||||||
Con *current = con_get_workspace(focused);
|
Con *current = con_get_workspace(focused);
|
||||||
Con *prev = NULL;
|
Con *prev = NULL;
|
||||||
Con *output = con_get_output(focused);
|
Con *output = con_get_output(focused);
|
||||||
DLOG("output = %s\n", output->name);
|
DLOG("output = %s\n", output->name);
|
||||||
|
|
||||||
if (current->num == -1) {
|
if (current->num == -1) {
|
||||||
@ -675,10 +671,10 @@ Con* workspace_prev_on_output(void) {
|
|||||||
prev = NULL;
|
prev = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* If numbered workspace, find previous numbered workspace. */
|
/* If numbered workspace, find previous numbered workspace. */
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE || child->num == -1)
|
if (child->type != CT_WORKSPACE || child->num == -1)
|
||||||
continue;
|
continue;
|
||||||
/* Need to check child against current and previous because we
|
/* Need to check child against current and previous because we
|
||||||
* are traversing multiple lists and thus are not guaranteed
|
* are traversing multiple lists and thus are not guaranteed
|
||||||
* the relative order between the list of workspaces. */
|
* the relative order between the list of workspaces. */
|
||||||
if (current->num > child->num && (!prev || child->num > prev->num))
|
if (current->num > child->num && (!prev || child->num > prev->num))
|
||||||
@ -689,7 +685,7 @@ Con* workspace_prev_on_output(void) {
|
|||||||
/* Find previous named workspace. */
|
/* Find previous named workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (child == current) {
|
if (child == current) {
|
||||||
@ -703,7 +699,7 @@ Con* workspace_prev_on_output(void) {
|
|||||||
|
|
||||||
/* Find last workspace. */
|
/* Find last workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE (output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
if (!prev || child->num > prev->num)
|
if (!prev || child->num > prev->num)
|
||||||
@ -746,11 +742,11 @@ Con *workspace_back_and_forth_get(void) {
|
|||||||
|
|
||||||
static bool get_urgency_flag(Con *con) {
|
static bool get_urgency_flag(Con *con) {
|
||||||
Con *child;
|
Con *child;
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (child, &(con->nodes_head), nodes)
|
||||||
if (child->urgent || get_urgency_flag(child))
|
if (child->urgent || get_urgency_flag(child))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->floating_head), floating_windows)
|
TAILQ_FOREACH (child, &(con->floating_head), floating_windows)
|
||||||
if (child->urgent || get_urgency_flag(child))
|
if (child->urgent || get_urgency_flag(child))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -859,7 +855,7 @@ Con *workspace_encapsulate(Con *ws) {
|
|||||||
new->layout = ws->layout;
|
new->layout = ws->layout;
|
||||||
|
|
||||||
DLOG("Moving children of workspace %p / %s into container %p\n",
|
DLOG("Moving children of workspace %p / %s into container %p\n",
|
||||||
ws, ws->name, new);
|
ws, ws->name, new);
|
||||||
|
|
||||||
Con *child;
|
Con *child;
|
||||||
while (!TAILQ_EMPTY(&(ws->nodes_head))) {
|
while (!TAILQ_EMPTY(&(ws->nodes_head))) {
|
||||||
|
159
src/x.c
159
src/x.c
@ -76,7 +76,7 @@ TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
|
|||||||
*/
|
*/
|
||||||
static con_state *state_for_frame(xcb_window_t window) {
|
static con_state *state_for_frame(xcb_window_t window) {
|
||||||
con_state *state;
|
con_state *state;
|
||||||
CIRCLEQ_FOREACH(state, &state_head, state)
|
CIRCLEQ_FOREACH (state, &state_head, state)
|
||||||
if (state->id == window)
|
if (state->id == window)
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ void x_con_init(Con *con, uint16_t depth) {
|
|||||||
values[2] = colormap;
|
values[2] = colormap;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect dims = { -15, -15, 10, 10 };
|
Rect dims = {-15, -15, 10, 10};
|
||||||
con->frame = create_window(conn, dims, depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
|
con->frame = create_window(conn, dims, depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
|
||||||
|
|
||||||
if (win_colormap != XCB_NONE)
|
if (win_colormap != XCB_NONE)
|
||||||
@ -214,7 +214,7 @@ void x_move_win(Con *src, Con *dest) {
|
|||||||
state_dest->con = state_src->con;
|
state_dest->con = state_src->con;
|
||||||
state_src->con = NULL;
|
state_src->con = NULL;
|
||||||
|
|
||||||
Rect zero = { 0, 0, 0, 0 };
|
Rect zero = {0, 0, 0, 0};
|
||||||
if (memcmp(&(state_dest->window_rect), &(zero), sizeof(Rect)) == 0) {
|
if (memcmp(&(state_dest->window_rect), &(zero), sizeof(Rect)) == 0) {
|
||||||
memcpy(&(state_dest->window_rect), &(state_src->window_rect), sizeof(Rect));
|
memcpy(&(state_dest->window_rect), &(state_src->window_rect), sizeof(Rect));
|
||||||
DLOG("COPYING RECT\n");
|
DLOG("COPYING RECT\n");
|
||||||
@ -296,7 +296,7 @@ void x_window_kill(xcb_window_t window, kill_window_t kill_window) {
|
|||||||
ev->data.data32[1] = XCB_CURRENT_TIME;
|
ev->data.data32[1] = XCB_CURRENT_TIME;
|
||||||
|
|
||||||
LOG("Sending WM_DELETE to the client\n");
|
LOG("Sending WM_DELETE to the client\n");
|
||||||
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char*)ev);
|
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)ev);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
@ -352,8 +352,8 @@ void x_draw_decoration(Con *con) {
|
|||||||
|
|
||||||
Rect *r = &(con->rect);
|
Rect *r = &(con->rect);
|
||||||
Rect *w = &(con->window_rect);
|
Rect *w = &(con->window_rect);
|
||||||
p->con_rect = (struct width_height){ r->width, r->height };
|
p->con_rect = (struct width_height) {r->width, r->height};
|
||||||
p->con_window_rect = (struct width_height){ w->width, w->height };
|
p->con_window_rect = (struct width_height) {w->width, w->height};
|
||||||
p->con_deco_rect = con->deco_rect;
|
p->con_deco_rect = con->deco_rect;
|
||||||
p->background = config.client.background;
|
p->background = config.client.background;
|
||||||
p->con_is_leaf = con_is_leaf(con);
|
p->con_is_leaf = con_is_leaf(con);
|
||||||
@ -386,14 +386,13 @@ void x_draw_decoration(Con *con) {
|
|||||||
if (con->window != NULL) {
|
if (con->window != NULL) {
|
||||||
xcb_rectangle_t background[] = {
|
xcb_rectangle_t background[] = {
|
||||||
/* top area */
|
/* top area */
|
||||||
{ 0, 0, r->width, w->y },
|
{0, 0, r->width, w->y},
|
||||||
/* bottom area */
|
/* bottom area */
|
||||||
{ 0, (w->y + w->height), r->width, r->height - (w->y + w->height) },
|
{0, (w->y + w->height), r->width, r->height - (w->y + w->height)},
|
||||||
/* left area */
|
/* left area */
|
||||||
{ 0, 0, w->x, r->height },
|
{0, 0, w->x, r->height},
|
||||||
/* right area */
|
/* right area */
|
||||||
{ w->x + w->width, 0, r->width - (w->x + w->width), r->height }
|
{w->x + w->width, 0, r->width - (w->x + w->width), r->height}};
|
||||||
};
|
|
||||||
#if 0
|
#if 0
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
DLOG("rect is (%d, %d) with %d x %d\n",
|
DLOG("rect is (%d, %d) with %d x %d\n",
|
||||||
@ -404,7 +403,7 @@ void x_draw_decoration(Con *con) {
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) { config.client.background });
|
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {config.client.background});
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, sizeof(background) / sizeof(xcb_rectangle_t), background);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, sizeof(background) / sizeof(xcb_rectangle_t), background);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,22 +424,22 @@ void x_draw_decoration(Con *con) {
|
|||||||
* (left, bottom and right part). We don’t just fill the whole
|
* (left, bottom and right part). We don’t just fill the whole
|
||||||
* rectangle because some childs are not freely resizable and we want
|
* rectangle because some childs are not freely resizable and we want
|
||||||
* their background color to "shine through". */
|
* their background color to "shine through". */
|
||||||
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
|
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
|
||||||
if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) {
|
if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) {
|
||||||
xcb_rectangle_t leftline = { 0, 0, br.x, r->height };
|
xcb_rectangle_t leftline = {0, 0, br.x, r->height};
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &leftline);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &leftline);
|
||||||
}
|
}
|
||||||
if (!(borders_to_hide & ADJ_RIGHT_SCREEN_EDGE)) {
|
if (!(borders_to_hide & ADJ_RIGHT_SCREEN_EDGE)) {
|
||||||
xcb_rectangle_t rightline = { r->width + br.width + br.x, 0, r->width, r->height };
|
xcb_rectangle_t rightline = {r->width + br.width + br.x, 0, r->width, r->height};
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &rightline);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &rightline);
|
||||||
}
|
}
|
||||||
if (!(borders_to_hide & ADJ_LOWER_SCREEN_EDGE)) {
|
if (!(borders_to_hide & ADJ_LOWER_SCREEN_EDGE)) {
|
||||||
xcb_rectangle_t bottomline = { 0, r->height + br.height + br.y, r->width, r->height };
|
xcb_rectangle_t bottomline = {0, r->height + br.height + br.y, r->width, r->height};
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &bottomline);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &bottomline);
|
||||||
}
|
}
|
||||||
/* 1pixel border needs an additional line at the top */
|
/* 1pixel border needs an additional line at the top */
|
||||||
if (p->border_style == BS_PIXEL && !(borders_to_hide & ADJ_UPPER_SCREEN_EDGE)) {
|
if (p->border_style == BS_PIXEL && !(borders_to_hide & ADJ_UPPER_SCREEN_EDGE)) {
|
||||||
xcb_rectangle_t topline = { br.x, 0, con->rect.width + br.width + br.x, br.y };
|
xcb_rectangle_t topline = {br.x, 0, con->rect.width + br.width + br.x, br.y};
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &topline);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &topline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,15 +450,14 @@ void x_draw_decoration(Con *con) {
|
|||||||
if (TAILQ_NEXT(con, nodes) == NULL &&
|
if (TAILQ_NEXT(con, nodes) == NULL &&
|
||||||
TAILQ_PREV(con, nodes_head, nodes) == NULL &&
|
TAILQ_PREV(con, nodes_head, nodes) == NULL &&
|
||||||
con->parent->type != CT_FLOATING_CON) {
|
con->parent->type != CT_FLOATING_CON) {
|
||||||
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->indicator });
|
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->indicator});
|
||||||
if (p->parent_layout == L_SPLITH)
|
if (p->parent_layout == L_SPLITH)
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) {
|
||||||
{ r->width + br.width + br.x, br.y, r->width, r->height + br.height } });
|
{r->width + br.width + br.x, br.y, r->width, r->height + br.height}});
|
||||||
else if (p->parent_layout == L_SPLITV)
|
else if (p->parent_layout == L_SPLITV)
|
||||||
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) {
|
||||||
{ br.x, r->height + br.height + br.y, r->width - (2 * br.x), r->height } });
|
{br.x, r->height + br.height + br.y, r->width - (2 * br.x), r->height}});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if this is a borderless/1pixel window, we don’t need to render the
|
/* if this is a borderless/1pixel window, we don’t need to render the
|
||||||
@ -468,12 +466,12 @@ void x_draw_decoration(Con *con) {
|
|||||||
goto copy_pixmaps;
|
goto copy_pixmaps;
|
||||||
|
|
||||||
/* 4: paint the bar */
|
/* 4: paint the bar */
|
||||||
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
|
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
|
||||||
xcb_rectangle_t drect = { con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height };
|
xcb_rectangle_t drect = {con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height};
|
||||||
xcb_poly_fill_rectangle(conn, parent->pixmap, parent->pm_gc, 1, &drect);
|
xcb_poly_fill_rectangle(conn, parent->pixmap, parent->pm_gc, 1, &drect);
|
||||||
|
|
||||||
/* 5: draw two unconnected horizontal lines in border color */
|
/* 5: draw two unconnected horizontal lines in border color */
|
||||||
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
|
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
|
||||||
Rect *dr = &(con->deco_rect);
|
Rect *dr = &(con->deco_rect);
|
||||||
int deco_diff_l = 2;
|
int deco_diff_l = 2;
|
||||||
int deco_diff_r = 2;
|
int deco_diff_r = 2;
|
||||||
@ -484,12 +482,10 @@ void x_draw_decoration(Con *con) {
|
|||||||
deco_diff_r = 0;
|
deco_diff_r = 0;
|
||||||
}
|
}
|
||||||
xcb_segment_t segments[] = {
|
xcb_segment_t segments[] = {
|
||||||
{ dr->x, dr->y,
|
{dr->x, dr->y,
|
||||||
dr->x + dr->width - 1, dr->y },
|
dr->x + dr->width - 1, dr->y},
|
||||||
|
{dr->x + deco_diff_l, dr->y + dr->height - 1,
|
||||||
{ dr->x + deco_diff_l, dr->y + dr->height - 1,
|
dr->x - deco_diff_r + dr->width - 1, dr->y + dr->height - 1}};
|
||||||
dr->x - deco_diff_r + dr->width - 1, dr->y + dr->height - 1 }
|
|
||||||
};
|
|
||||||
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
|
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
|
||||||
|
|
||||||
/* 6: draw the title */
|
/* 6: draw the title */
|
||||||
@ -507,9 +503,9 @@ void x_draw_decoration(Con *con) {
|
|||||||
free(tree);
|
free(tree);
|
||||||
|
|
||||||
draw_text_ascii(title,
|
draw_text_ascii(title,
|
||||||
parent->pixmap, parent->pm_gc,
|
parent->pixmap, parent->pm_gc,
|
||||||
con->deco_rect.x + 2, con->deco_rect.y + text_offset_y,
|
con->deco_rect.x + 2, con->deco_rect.y + text_offset_y,
|
||||||
con->deco_rect.width - 2);
|
con->deco_rect.width - 2);
|
||||||
free(title);
|
free(title);
|
||||||
|
|
||||||
goto after_title;
|
goto after_title;
|
||||||
@ -536,9 +532,9 @@ void x_draw_decoration(Con *con) {
|
|||||||
int indent_px = (indent_level * 5) * indent_mult;
|
int indent_px = (indent_level * 5) * indent_mult;
|
||||||
|
|
||||||
draw_text(win->name,
|
draw_text(win->name,
|
||||||
parent->pixmap, parent->pm_gc,
|
parent->pixmap, parent->pm_gc,
|
||||||
con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
|
con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
|
||||||
con->deco_rect.width - 2 - indent_px);
|
con->deco_rect.width - 2 - indent_px);
|
||||||
|
|
||||||
after_title:
|
after_title:
|
||||||
/* Since we don’t clip the text at all, it might in some cases be painted
|
/* Since we don’t clip the text at all, it might in some cases be painted
|
||||||
@ -549,21 +545,21 @@ after_title:
|
|||||||
/* Draw a 1px separator line before and after every tab, so that tabs can
|
/* Draw a 1px separator line before and after every tab, so that tabs can
|
||||||
* be easily distinguished. */
|
* be easily distinguished. */
|
||||||
if (parent->layout == L_TABBED) {
|
if (parent->layout == L_TABBED) {
|
||||||
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
|
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
|
||||||
} else {
|
} else {
|
||||||
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
|
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
|
||||||
}
|
}
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, parent->pixmap, parent->pm_gc, 6,
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, parent->pixmap, parent->pm_gc, 6,
|
||||||
(xcb_point_t[]){
|
(xcb_point_t[]) {
|
||||||
{ dr->x + dr->width, dr->y },
|
{dr->x + dr->width, dr->y},
|
||||||
{ dr->x + dr->width, dr->y + dr->height },
|
{dr->x + dr->width, dr->y + dr->height},
|
||||||
{ dr->x + dr->width - 1, dr->y },
|
{dr->x + dr->width - 1, dr->y},
|
||||||
{ dr->x + dr->width - 1, dr->y + dr->height },
|
{dr->x + dr->width - 1, dr->y + dr->height},
|
||||||
{ dr->x, dr->y + dr->height },
|
{dr->x, dr->y + dr->height},
|
||||||
{ dr->x, dr->y },
|
{dr->x, dr->y},
|
||||||
});
|
});
|
||||||
|
|
||||||
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
|
xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
|
||||||
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
|
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
|
||||||
|
|
||||||
copy_pixmaps:
|
copy_pixmaps:
|
||||||
@ -583,10 +579,10 @@ void x_deco_recurse(Con *con) {
|
|||||||
con_state *state = state_for_frame(con->frame);
|
con_state *state = state_for_frame(con->frame);
|
||||||
|
|
||||||
if (!leaf) {
|
if (!leaf) {
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes)
|
||||||
x_deco_recurse(current);
|
x_deco_recurse(current);
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
TAILQ_FOREACH (current, &(con->floating_head), floating_windows)
|
||||||
x_deco_recurse(current);
|
x_deco_recurse(current);
|
||||||
|
|
||||||
if (state->mapped)
|
if (state->mapped)
|
||||||
@ -624,7 +620,7 @@ void x_push_node(Con *con) {
|
|||||||
/* Calculate the height of all window decorations which will be drawn on to
|
/* Calculate the height of all window decorations which will be drawn on to
|
||||||
* this frame. */
|
* this frame. */
|
||||||
uint32_t max_y = 0, max_height = 0;
|
uint32_t max_y = 0, max_height = 0;
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes) {
|
||||||
Rect *dr = &(current->deco_rect);
|
Rect *dr = &(current->deco_rect);
|
||||||
if (dr->y >= max_y && dr->height >= max_height) {
|
if (dr->y >= max_y && dr->height >= max_height) {
|
||||||
max_y = dr->y;
|
max_y = dr->y;
|
||||||
@ -644,7 +640,7 @@ void x_push_node(Con *con) {
|
|||||||
/* Temporarily set the event masks to XCB_NONE so that we won’t get
|
/* Temporarily set the event masks to XCB_NONE so that we won’t get
|
||||||
* UnmapNotify events (otherwise the handler would close the container).
|
* UnmapNotify events (otherwise the handler would close the container).
|
||||||
* These events are generated automatically when reparenting. */
|
* These events are generated automatically when reparenting. */
|
||||||
uint32_t values[] = { XCB_NONE };
|
uint32_t values[] = {XCB_NONE};
|
||||||
xcb_change_window_attributes(conn, state->old_frame, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, state->old_frame, XCB_CW_EVENT_MASK, values);
|
||||||
xcb_change_window_attributes(conn, con->window->id, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, con->window->id, XCB_CW_EVENT_MASK, values);
|
||||||
|
|
||||||
@ -660,7 +656,7 @@ void x_push_node(Con *con) {
|
|||||||
|
|
||||||
con->ignore_unmap++;
|
con->ignore_unmap++;
|
||||||
DLOG("ignore_unmap for reparenting of con %p (win 0x%08x) is now %d\n",
|
DLOG("ignore_unmap for reparenting of con %p (win 0x%08x) is now %d\n",
|
||||||
con, con->window->id, con->ignore_unmap);
|
con, con->window->id, con->ignore_unmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fake_notify = false;
|
bool fake_notify = false;
|
||||||
@ -680,9 +676,9 @@ void x_push_node(Con *con) {
|
|||||||
/* The pixmap of a borderless leaf container will not be used except
|
/* The pixmap of a borderless leaf container will not be used except
|
||||||
* for the titlebar in a stack or tabs (issue #1013). */
|
* for the titlebar in a stack or tabs (issue #1013). */
|
||||||
bool is_pixmap_needed = (con->border_style != BS_NONE ||
|
bool is_pixmap_needed = (con->border_style != BS_NONE ||
|
||||||
!con_is_leaf(con) ||
|
!con_is_leaf(con) ||
|
||||||
con->parent->layout == L_STACKED ||
|
con->parent->layout == L_STACKED ||
|
||||||
con->parent->layout == L_TABBED);
|
con->parent->layout == L_TABBED);
|
||||||
|
|
||||||
/* Check if the container has an unneeded pixmap left over from
|
/* Check if the container has an unneeded pixmap left over from
|
||||||
* previously having a border or titlebar. */
|
* previously having a border or titlebar. */
|
||||||
@ -711,7 +707,7 @@ void x_push_node(Con *con) {
|
|||||||
* properly due to parts of the source being unmapped or otherwise
|
* properly due to parts of the source being unmapped or otherwise
|
||||||
* unavailable. Since we always copy from pixmaps to windows, this
|
* unavailable. Since we always copy from pixmaps to windows, this
|
||||||
* is not a concern for us. */
|
* is not a concern for us. */
|
||||||
uint32_t values[] = { 0 };
|
uint32_t values[] = {0};
|
||||||
xcb_create_gc(conn, con->pm_gc, con->pixmap, XCB_GC_GRAPHICS_EXPOSURES, values);
|
xcb_create_gc(conn, con->pm_gc, con->pixmap, XCB_GC_GRAPHICS_EXPOSURES, values);
|
||||||
|
|
||||||
con->pixmap_recreated = true;
|
con->pixmap_recreated = true;
|
||||||
@ -746,7 +742,7 @@ void x_push_node(Con *con) {
|
|||||||
if (con->window != NULL &&
|
if (con->window != NULL &&
|
||||||
memcmp(&(state->window_rect), &(con->window_rect), sizeof(Rect)) != 0) {
|
memcmp(&(state->window_rect), &(con->window_rect), sizeof(Rect)) != 0) {
|
||||||
DLOG("setting window rect (%d, %d, %d, %d)\n",
|
DLOG("setting window rect (%d, %d, %d, %d)\n",
|
||||||
con->window_rect.x, con->window_rect.y, con->window_rect.width, con->window_rect.height);
|
con->window_rect.x, con->window_rect.y, con->window_rect.width, con->window_rect.height);
|
||||||
xcb_set_window_rect(conn, con->window->id, con->window_rect);
|
xcb_set_window_rect(conn, con->window->id, con->window_rect);
|
||||||
memcpy(&(state->window_rect), &(con->window_rect), sizeof(Rect));
|
memcpy(&(state->window_rect), &(con->window_rect), sizeof(Rect));
|
||||||
fake_notify = true;
|
fake_notify = true;
|
||||||
@ -762,7 +758,7 @@ void x_push_node(Con *con) {
|
|||||||
if (con->window != NULL) {
|
if (con->window != NULL) {
|
||||||
/* Set WM_STATE_NORMAL because GTK applications don’t want to
|
/* Set WM_STATE_NORMAL because GTK applications don’t want to
|
||||||
* drag & drop if we don’t. Also, xprop(1) needs it. */
|
* drag & drop if we don’t. Also, xprop(1) needs it. */
|
||||||
long data[] = { XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE };
|
long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE};
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
|
||||||
A_WM_STATE, A_WM_STATE, 32, 2, data);
|
A_WM_STATE, A_WM_STATE, 32, 2, data);
|
||||||
}
|
}
|
||||||
@ -803,7 +799,7 @@ void x_push_node(Con *con) {
|
|||||||
/* Handle all children and floating windows of this node. We recurse
|
/* Handle all children and floating windows of this node. We recurse
|
||||||
* in focus order to display the focused client in a stack first when
|
* in focus order to display the focused client in a stack first when
|
||||||
* switching workspaces (reduces flickering). */
|
* switching workspaces (reduces flickering). */
|
||||||
TAILQ_FOREACH(current, &(con->focus_head), focused)
|
TAILQ_FOREACH (current, &(con->focus_head), focused)
|
||||||
x_push_node(current);
|
x_push_node(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,7 +826,7 @@ static void x_push_node_unmaps(Con *con) {
|
|||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
if (con->window != NULL) {
|
if (con->window != NULL) {
|
||||||
/* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */
|
/* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */
|
||||||
long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
|
long data[] = {XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE};
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
|
||||||
A_WM_STATE, A_WM_STATE, 32, 2, data);
|
A_WM_STATE, A_WM_STATE, 32, 2, data);
|
||||||
}
|
}
|
||||||
@ -848,10 +844,10 @@ static void x_push_node_unmaps(Con *con) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle all children and floating windows of this node */
|
/* handle all children and floating windows of this node */
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes)
|
TAILQ_FOREACH (current, &(con->nodes_head), nodes)
|
||||||
x_push_node_unmaps(current);
|
x_push_node_unmaps(current);
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
TAILQ_FOREACH (current, &(con->floating_head), floating_windows)
|
||||||
x_push_node_unmaps(current);
|
x_push_node_unmaps(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +861,7 @@ static bool is_con_attached(Con *con) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
Con *current;
|
Con *current;
|
||||||
TAILQ_FOREACH(current, &(con->parent->nodes_head), nodes) {
|
TAILQ_FOREACH (current, &(con->parent->nodes_head), nodes) {
|
||||||
if (current == con)
|
if (current == con)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -895,8 +891,8 @@ void x_push_changes(Con *con) {
|
|||||||
|
|
||||||
DLOG("-- PUSHING WINDOW STACK --\n");
|
DLOG("-- PUSHING WINDOW STACK --\n");
|
||||||
//DLOG("Disabling EnterNotify\n");
|
//DLOG("Disabling EnterNotify\n");
|
||||||
uint32_t values[1] = { XCB_NONE };
|
uint32_t values[1] = {XCB_NONE};
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
|
||||||
if (state->mapped)
|
if (state->mapped)
|
||||||
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
||||||
}
|
}
|
||||||
@ -907,7 +903,7 @@ void x_push_changes(Con *con) {
|
|||||||
/* count first, necessary to (re)allocate memory for the bottom-to-top
|
/* count first, necessary to (re)allocate memory for the bottom-to-top
|
||||||
* stack afterwards */
|
* stack afterwards */
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state)
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state)
|
||||||
if (con_has_managed_window(state->con))
|
if (con_has_managed_window(state->con))
|
||||||
cnt++;
|
cnt++;
|
||||||
|
|
||||||
@ -924,7 +920,7 @@ void x_push_changes(Con *con) {
|
|||||||
xcb_window_t *walk = client_list_windows;
|
xcb_window_t *walk = client_list_windows;
|
||||||
|
|
||||||
/* X11 correctly represents the stack if we push it from bottom to top */
|
/* X11 correctly represents the stack if we push it from bottom to top */
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
|
||||||
if (con_has_managed_window(state->con))
|
if (con_has_managed_window(state->con))
|
||||||
memcpy(walk++, &(state->con->window->id), sizeof(xcb_window_t));
|
memcpy(walk++, &(state->con->window->id), sizeof(xcb_window_t));
|
||||||
|
|
||||||
@ -955,7 +951,7 @@ void x_push_changes(Con *con) {
|
|||||||
walk = client_list_windows;
|
walk = client_list_windows;
|
||||||
|
|
||||||
/* reorder by initial mapping */
|
/* reorder by initial mapping */
|
||||||
TAILQ_FOREACH(state, &initial_mapping_head, initial_mapping_order) {
|
TAILQ_FOREACH (state, &initial_mapping_head, initial_mapping_order) {
|
||||||
if (con_has_managed_window(state->con))
|
if (con_has_managed_window(state->con))
|
||||||
*walk++ = state->con->window->id;
|
*walk++ = state->con->window->id;
|
||||||
}
|
}
|
||||||
@ -978,9 +974,9 @@ void x_push_changes(Con *con) {
|
|||||||
Output *target = get_output_containing(mid_x, mid_y);
|
Output *target = get_output_containing(mid_x, mid_y);
|
||||||
if (current != target) {
|
if (current != target) {
|
||||||
/* Ignore MotionNotify events generated by warping */
|
/* Ignore MotionNotify events generated by warping */
|
||||||
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT });
|
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
|
||||||
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
|
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
|
||||||
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ ROOT_EVENT_MASK });
|
xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warp_to = NULL;
|
warp_to = NULL;
|
||||||
@ -988,7 +984,7 @@ void x_push_changes(Con *con) {
|
|||||||
|
|
||||||
//DLOG("Re-enabling EnterNotify\n");
|
//DLOG("Re-enabling EnterNotify\n");
|
||||||
values[0] = FRAME_EVENT_MASK;
|
values[0] = FRAME_EVENT_MASK;
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
|
||||||
if (state->mapped)
|
if (state->mapped)
|
||||||
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
||||||
}
|
}
|
||||||
@ -1016,7 +1012,7 @@ void x_push_changes(Con *con) {
|
|||||||
ewmh_update_active_window((con_has_managed_window(focused) ? focused->window->id : XCB_WINDOW_NONE));
|
ewmh_update_active_window((con_has_managed_window(focused) ? focused->window->id : XCB_WINDOW_NONE));
|
||||||
|
|
||||||
if (to_focus != last_focused && is_con_attached(focused))
|
if (to_focus != last_focused && is_con_attached(focused))
|
||||||
ipc_send_window_event("focus", focused);
|
ipc_send_window_event("focus", focused);
|
||||||
} else {
|
} else {
|
||||||
DLOG("Updating focus (focused: %p / %s) to X11 window 0x%08x\n", focused, focused->name, to_focus);
|
DLOG("Updating focus (focused: %p / %s) to X11 window 0x%08x\n", focused, focused->name, to_focus);
|
||||||
/* We remove XCB_EVENT_MASK_FOCUS_CHANGE from the event mask to get
|
/* We remove XCB_EVENT_MASK_FOCUS_CHANGE from the event mask to get
|
||||||
@ -1035,7 +1031,7 @@ void x_push_changes(Con *con) {
|
|||||||
ewmh_update_active_window((con_has_managed_window(focused) ? focused->window->id : XCB_WINDOW_NONE));
|
ewmh_update_active_window((con_has_managed_window(focused) ? focused->window->id : XCB_WINDOW_NONE));
|
||||||
|
|
||||||
if (to_focus != XCB_NONE && to_focus != last_focused && focused->window != NULL && is_con_attached(focused))
|
if (to_focus != XCB_NONE && to_focus != last_focused && focused->window != NULL && is_con_attached(focused))
|
||||||
ipc_send_window_event("focus", focused);
|
ipc_send_window_event("focus", focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
focused_id = last_focused = to_focus;
|
focused_id = last_focused = to_focus;
|
||||||
@ -1060,7 +1056,7 @@ void x_push_changes(Con *con) {
|
|||||||
* unmapped, the second one appears under the cursor and therefore gets an
|
* unmapped, the second one appears under the cursor and therefore gets an
|
||||||
* EnterNotify event. */
|
* EnterNotify event. */
|
||||||
values[0] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
|
values[0] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
|
||||||
if (!state->unmap_now)
|
if (!state->unmap_now)
|
||||||
continue;
|
continue;
|
||||||
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
||||||
@ -1070,7 +1066,7 @@ void x_push_changes(Con *con) {
|
|||||||
x_push_node_unmaps(con);
|
x_push_node_unmaps(con);
|
||||||
|
|
||||||
/* save the current stack as old stack */
|
/* save the current stack as old stack */
|
||||||
CIRCLEQ_FOREACH(state, &state_head, state) {
|
CIRCLEQ_FOREACH (state, &state_head, state) {
|
||||||
CIRCLEQ_REMOVE(&old_state_head, state, old_state);
|
CIRCLEQ_REMOVE(&old_state_head, state, old_state);
|
||||||
CIRCLEQ_INSERT_TAIL(&old_state_head, state, old_state);
|
CIRCLEQ_INSERT_TAIL(&old_state_head, state, old_state);
|
||||||
}
|
}
|
||||||
@ -1119,8 +1115,8 @@ void x_set_name(Con *con, const char *name) {
|
|||||||
*/
|
*/
|
||||||
void update_shmlog_atom() {
|
void update_shmlog_atom() {
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
|
||||||
A_I3_SHMLOG_PATH, A_UTF8_STRING, 8,
|
A_I3_SHMLOG_PATH, A_UTF8_STRING, 8,
|
||||||
strlen(shmlogname), shmlogname);
|
strlen(shmlogname), shmlogname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1143,8 +1139,7 @@ void x_set_i3_atoms(void) {
|
|||||||
* x_push_changes().
|
* x_push_changes().
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void x_set_warp_to(Rect *rect)
|
void x_set_warp_to(Rect *rect) {
|
||||||
{
|
|
||||||
if (!config.disable_focus_follows_mouse &&
|
if (!config.disable_focus_follows_mouse &&
|
||||||
config.mouse_warping != POINTER_WARPING_NONE)
|
config.mouse_warping != POINTER_WARPING_NONE)
|
||||||
warp_to = rect;
|
warp_to = rect;
|
||||||
@ -1157,10 +1152,10 @@ void x_set_warp_to(Rect *rect)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void x_mask_event_mask(uint32_t mask) {
|
void x_mask_event_mask(uint32_t mask) {
|
||||||
uint32_t values[] = { FRAME_EVENT_MASK & mask };
|
uint32_t values[] = {FRAME_EVENT_MASK & mask};
|
||||||
|
|
||||||
con_state *state;
|
con_state *state;
|
||||||
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
|
CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
|
||||||
if (state->mapped)
|
if (state->mapped)
|
||||||
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
|
||||||
}
|
}
|
||||||
|
55
src/xcb.c
55
src/xcb.c
@ -19,8 +19,8 @@ unsigned int xcb_numlock_mask;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
|
xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
|
||||||
uint16_t depth, xcb_visualid_t visual, uint16_t window_class,
|
uint16_t depth, xcb_visualid_t visual, uint16_t window_class,
|
||||||
enum xcursor_cursor_t cursor, bool map, uint32_t mask, uint32_t *values) {
|
enum xcursor_cursor_t cursor, bool map, uint32_t mask, uint32_t *values) {
|
||||||
xcb_window_t result = xcb_generate_id(conn);
|
xcb_window_t result = xcb_generate_id(conn);
|
||||||
|
|
||||||
/* If the window class is XCB_WINDOW_CLASS_INPUT_ONLY, we copy depth and
|
/* If the window class is XCB_WINDOW_CLASS_INPUT_ONLY, we copy depth and
|
||||||
@ -31,15 +31,15 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_create_window(conn,
|
xcb_create_window(conn,
|
||||||
depth,
|
depth,
|
||||||
result, /* the window id */
|
result, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
dims.x, dims.y, dims.width, dims.height, /* dimensions */
|
dims.x, dims.y, dims.width, dims.height, /* dimensions */
|
||||||
0, /* border = 0, we draw our own */
|
0, /* border = 0, we draw our own */
|
||||||
window_class,
|
window_class,
|
||||||
visual,
|
visual,
|
||||||
mask,
|
mask,
|
||||||
values);
|
values);
|
||||||
|
|
||||||
/* Set the cursor */
|
/* Set the cursor */
|
||||||
if (xcursor_supported) {
|
if (xcursor_supported) {
|
||||||
@ -51,8 +51,8 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
|
|||||||
i3Font cursor_font = load_font("cursor", false);
|
i3Font cursor_font = load_font("cursor", false);
|
||||||
int xcb_cursor = xcursor_get_xcb_cursor(cursor);
|
int xcb_cursor = xcursor_get_xcb_cursor(cursor);
|
||||||
xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
|
xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
|
||||||
cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
|
cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
|
||||||
65535, 65535, 65535);
|
65535, 65535, 65535);
|
||||||
xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
|
xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
|
||||||
xcb_free_cursor(conn, cursor_id);
|
xcb_free_cursor(conn, cursor_id);
|
||||||
}
|
}
|
||||||
@ -70,9 +70,9 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
|
|||||||
*/
|
*/
|
||||||
void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
|
void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
|
||||||
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t to_x, uint32_t to_y) {
|
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t to_x, uint32_t to_y) {
|
||||||
xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ colorpixel });
|
xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel});
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2,
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2,
|
||||||
(xcb_point_t[]) { {x, y}, {to_x, to_y} });
|
(xcb_point_t[]) {{x, y}, {to_x, to_y}});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -81,7 +81,7 @@ void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext
|
|||||||
*/
|
*/
|
||||||
void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
|
void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
|
||||||
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
||||||
xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ colorpixel });
|
xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel});
|
||||||
xcb_rectangle_t rect = {x, y, width, height};
|
xcb_rectangle_t rect = {x, y, width, height};
|
||||||
xcb_poly_fill_rectangle(conn, drawable, gc, 1, &rect);
|
xcb_poly_fill_rectangle(conn, drawable, gc, 1, &rect);
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ void send_take_focus(xcb_window_t window, xcb_timestamp_t timestamp) {
|
|||||||
ev->data.data32[1] = timestamp;
|
ev->data.data32[1] = timestamp;
|
||||||
|
|
||||||
DLOG("Sending WM_TAKE_FOCUS to the client\n");
|
DLOG("Sending WM_TAKE_FOCUS to the client\n");
|
||||||
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char*)ev);
|
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)ev);
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ void send_take_focus(xcb_window_t window, xcb_timestamp_t timestamp) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window) {
|
void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window) {
|
||||||
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
uint32_t values[] = {XCB_STACK_MODE_ABOVE};
|
||||||
xcb_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
xcb_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,11 +145,11 @@ void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window) {
|
|||||||
void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r) {
|
void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r) {
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
cookie = xcb_configure_window(conn, window,
|
cookie = xcb_configure_window(conn, window,
|
||||||
XCB_CONFIG_WINDOW_X |
|
XCB_CONFIG_WINDOW_X |
|
||||||
XCB_CONFIG_WINDOW_Y |
|
XCB_CONFIG_WINDOW_Y |
|
||||||
XCB_CONFIG_WINDOW_WIDTH |
|
XCB_CONFIG_WINDOW_WIDTH |
|
||||||
XCB_CONFIG_WINDOW_HEIGHT,
|
XCB_CONFIG_WINDOW_HEIGHT,
|
||||||
&(r.x));
|
&(r.x));
|
||||||
/* ignore events which are generated because we configured a window */
|
/* ignore events which are generated because we configured a window */
|
||||||
add_ignore_event(cookie.sequence, -1);
|
add_ignore_event(cookie.sequence, -1);
|
||||||
}
|
}
|
||||||
@ -171,7 +171,6 @@ bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,8 +196,8 @@ void xcb_set_root_cursor(int cursor) {
|
|||||||
i3Font cursor_font = load_font("cursor", false);
|
i3Font cursor_font = load_font("cursor", false);
|
||||||
int xcb_cursor = xcursor_get_xcb_cursor(cursor);
|
int xcb_cursor = xcursor_get_xcb_cursor(cursor);
|
||||||
xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
|
xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
|
||||||
cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
|
cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
|
||||||
65535, 65535, 65535);
|
65535, 65535, 65535);
|
||||||
xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, &cursor_id);
|
xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, &cursor_id);
|
||||||
xcb_free_cursor(conn, cursor_id);
|
xcb_free_cursor(conn, cursor_id);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
@ -208,7 +207,7 @@ void xcb_set_root_cursor(int cursor) {
|
|||||||
* Get depth of visual specified by visualid
|
* Get depth of visual specified by visualid
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint16_t get_visual_depth(xcb_visualid_t visual_id){
|
uint16_t get_visual_depth(xcb_visualid_t visual_id) {
|
||||||
xcb_depth_iterator_t depth_iter;
|
xcb_depth_iterator_t depth_iter;
|
||||||
|
|
||||||
depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
|
depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
|
||||||
@ -229,7 +228,7 @@ uint16_t get_visual_depth(xcb_visualid_t visual_id){
|
|||||||
* Get visualid with specified depth
|
* Get visualid with specified depth
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
xcb_visualid_t get_visualid_by_depth(uint16_t depth){
|
xcb_visualid_t get_visualid_by_depth(uint16_t depth) {
|
||||||
xcb_depth_iterator_t depth_iter;
|
xcb_depth_iterator_t depth_iter;
|
||||||
|
|
||||||
depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
|
depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
|
||||||
|
@ -23,8 +23,7 @@ static const int xcb_cursors[XCURSOR_CURSOR_MAX] = {
|
|||||||
XCB_CURSOR_LEFT_PTR,
|
XCB_CURSOR_LEFT_PTR,
|
||||||
XCB_CURSOR_SB_H_DOUBLE_ARROW,
|
XCB_CURSOR_SB_H_DOUBLE_ARROW,
|
||||||
XCB_CURSOR_SB_V_DOUBLE_ARROW,
|
XCB_CURSOR_SB_V_DOUBLE_ARROW,
|
||||||
XCB_CURSOR_WATCH
|
XCB_CURSOR_WATCH};
|
||||||
};
|
|
||||||
|
|
||||||
void xcursor_load_cursors(void) {
|
void xcursor_load_cursors(void) {
|
||||||
if (xcb_cursor_context_new(conn, root_screen, &ctx) < 0) {
|
if (xcb_cursor_context_new(conn, root_screen, &ctx) < 0) {
|
||||||
@ -32,8 +31,8 @@ void xcursor_load_cursors(void) {
|
|||||||
xcursor_supported = false;
|
xcursor_supported = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#define LOAD_CURSOR(constant, name) \
|
#define LOAD_CURSOR(constant, name) \
|
||||||
do { \
|
do { \
|
||||||
cursors[constant] = xcb_cursor_load_cursor(ctx, name); \
|
cursors[constant] = xcb_cursor_load_cursor(ctx, name); \
|
||||||
} while (0)
|
} while (0)
|
||||||
LOAD_CURSOR(XCURSOR_CURSOR_POINTER, "left_ptr");
|
LOAD_CURSOR(XCURSOR_CURSOR_POINTER, "left_ptr");
|
||||||
@ -57,7 +56,7 @@ void xcursor_load_cursors(void) {
|
|||||||
*/
|
*/
|
||||||
void xcursor_set_root_cursor(int cursor_id) {
|
void xcursor_set_root_cursor(int cursor_id) {
|
||||||
xcb_change_window_attributes(conn, root, XCB_CW_CURSOR,
|
xcb_change_window_attributes(conn, root, XCB_CW_CURSOR,
|
||||||
(uint32_t[]){ xcursor_get_cursor(cursor_id) });
|
(uint32_t[]) {xcursor_get_cursor(cursor_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) {
|
xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) {
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
|
|
||||||
|
|
||||||
static int num_screens;
|
static int num_screens;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -24,7 +23,7 @@ static int num_screens;
|
|||||||
*/
|
*/
|
||||||
static Output *get_screen_at(unsigned int x, unsigned int y) {
|
static Output *get_screen_at(unsigned int x, unsigned int y) {
|
||||||
Output *output;
|
Output *output;
|
||||||
TAILQ_FOREACH(output, &outputs, outputs)
|
TAILQ_FOREACH (output, &outputs, outputs)
|
||||||
if (output->rect.x == x && output->rect.y == y)
|
if (output->rect.x == x && output->rect.y == y)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
@ -67,16 +66,17 @@ static void query_screens(xcb_connection_t *conn) {
|
|||||||
s->rect.height = screen_info[screen].height;
|
s->rect.height = screen_info[screen].height;
|
||||||
/* We always treat the screen at 0x0 as the primary screen */
|
/* We always treat the screen at 0x0 as the primary screen */
|
||||||
if (s->rect.x == 0 && s->rect.y == 0)
|
if (s->rect.x == 0 && s->rect.y == 0)
|
||||||
TAILQ_INSERT_HEAD(&outputs, s, outputs);
|
TAILQ_INSERT_HEAD(&outputs, s, outputs);
|
||||||
else TAILQ_INSERT_TAIL(&outputs, s, outputs);
|
else
|
||||||
|
TAILQ_INSERT_TAIL(&outputs, s, outputs);
|
||||||
output_init_con(s);
|
output_init_con(s);
|
||||||
init_ws_for_output(s, output_get_content(s->con));
|
init_ws_for_output(s, output_get_content(s->con));
|
||||||
num_screens++;
|
num_screens++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG("found Xinerama screen: %d x %d at %d x %d\n",
|
DLOG("found Xinerama screen: %d x %d at %d x %d\n",
|
||||||
screen_info[screen].width, screen_info[screen].height,
|
screen_info[screen].width, screen_info[screen].height,
|
||||||
screen_info[screen].x_org, screen_info[screen].y_org);
|
screen_info[screen].x_org, screen_info[screen].y_org);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(reply);
|
free(reply);
|
||||||
|
33
tests/swap.c
33
tests/swap.c
@ -24,27 +24,28 @@ void dump() {
|
|||||||
printf("first: %d\n", e->abc);
|
printf("first: %d\n", e->abc);
|
||||||
e = TAILQ_LAST(&head, objhead);
|
e = TAILQ_LAST(&head, objhead);
|
||||||
printf("last: %d\n", e->abc);
|
printf("last: %d\n", e->abc);
|
||||||
TAILQ_FOREACH(e, &head, entry) {
|
TAILQ_FOREACH (e, &head, entry) {
|
||||||
printf(" %d\n", e->abc);
|
printf(" %d\n", e->abc);
|
||||||
}
|
}
|
||||||
printf("again, but reverse:\n");
|
printf("again, but reverse:\n");
|
||||||
TAILQ_FOREACH_REVERSE(e, &head, objhead, entry) {
|
TAILQ_FOREACH_REVERSE (e, &head, objhead, entry) {
|
||||||
printf(" %d\n", e->abc);
|
printf(" %d\n", e->abc);
|
||||||
}
|
}
|
||||||
printf("done\n\n");
|
printf("done\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TAILQ_SWAP(first, second, head, field) do { \
|
#define TAILQ_SWAP(first, second, head, field) \
|
||||||
*((first)->field.tqe_prev) = (second); \
|
do { \
|
||||||
(second)->field.tqe_prev = (first)->field.tqe_prev; \
|
*((first)->field.tqe_prev) = (second); \
|
||||||
(first)->field.tqe_prev = &((second)->field.tqe_next); \
|
(second)->field.tqe_prev = (first)->field.tqe_prev; \
|
||||||
(first)->field.tqe_next = (second)->field.tqe_next; \
|
(first)->field.tqe_prev = &((second)->field.tqe_next); \
|
||||||
if ((second)->field.tqe_next) \
|
(first)->field.tqe_next = (second)->field.tqe_next; \
|
||||||
(second)->field.tqe_next->field.tqe_prev = &((first)->field.tqe_next); \
|
if ((second)->field.tqe_next) \
|
||||||
(second)->field.tqe_next = first; \
|
(second)->field.tqe_next->field.tqe_prev = &((first)->field.tqe_next); \
|
||||||
if ((head)->tqh_last == &((second)->field.tqe_next)) \
|
(second)->field.tqe_next = first; \
|
||||||
(head)->tqh_last = &((first)->field.tqe_next); \
|
if ((head)->tqh_last == &((second)->field.tqe_next)) \
|
||||||
} while (0)
|
(head)->tqh_last = &((first)->field.tqe_next); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
void _TAILQ_SWAP(struct obj *first, struct obj *second, struct objhead *head) {
|
void _TAILQ_SWAP(struct obj *first, struct obj *second, struct objhead *head) {
|
||||||
struct obj **tqe_prev = first->entry.tqe_prev;
|
struct obj **tqe_prev = first->entry.tqe_prev;
|
||||||
@ -65,7 +66,6 @@ void _TAILQ_SWAP(struct obj *first, struct obj *second, struct objhead *head) {
|
|||||||
|
|
||||||
if (head->tqh_last == &(second->entry.tqe_next))
|
if (head->tqh_last == &(second->entry.tqe_next))
|
||||||
head->tqh_last = &(first->entry.tqe_next);
|
head->tqh_last = &(first->entry.tqe_next);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@ -85,7 +85,6 @@ int main() {
|
|||||||
struct obj fourth;
|
struct obj fourth;
|
||||||
fourth.abc = 999;
|
fourth.abc = 999;
|
||||||
|
|
||||||
|
|
||||||
struct obj fifth;
|
struct obj fifth;
|
||||||
fifth.abc = 5555;
|
fifth.abc = 5555;
|
||||||
|
|
||||||
@ -157,7 +156,6 @@ int main() {
|
|||||||
|
|
||||||
dump();
|
dump();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ************************************************
|
* ************************************************
|
||||||
*/
|
*/
|
||||||
@ -180,7 +178,6 @@ int main() {
|
|||||||
|
|
||||||
dump();
|
dump();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ************************************************
|
* ************************************************
|
||||||
*/
|
*/
|
||||||
@ -203,7 +200,6 @@ int main() {
|
|||||||
|
|
||||||
dump();
|
dump();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ************************************************
|
* ************************************************
|
||||||
*/
|
*/
|
||||||
@ -225,5 +221,4 @@ int main() {
|
|||||||
TAILQ_REMOVE(&head, &second, entry);
|
TAILQ_REMOVE(&head, &second, entry);
|
||||||
|
|
||||||
dump();
|
dump();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,28 @@
|
|||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
|
||||||
void print_table() {
|
void print_table() {
|
||||||
int r, c;
|
int r, c;
|
||||||
printf("printing table...\n");
|
printf("printing table...\n");
|
||||||
for (c = 0; c < table_dims.x; c++)
|
for (c = 0; c < table_dims.x; c++)
|
||||||
for (r = 0; r < table_dims.y; r++)
|
for (r = 0; r < table_dims.y; r++)
|
||||||
printf("table[%d][%d] = %p\n", c, r, table[c][r]);
|
printf("table[%d][%d] = %p\n", c, r, table[c][r]);
|
||||||
printf("done\n");
|
printf("done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("table.c tests\n");
|
printf("table.c tests\n");
|
||||||
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
||||||
init_table();
|
init_table();
|
||||||
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
||||||
print_table();
|
print_table();
|
||||||
|
|
||||||
printf("expand_table_cols()\n");
|
printf("expand_table_cols()\n");
|
||||||
expand_table_cols();
|
expand_table_cols();
|
||||||
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
||||||
print_table();
|
print_table();
|
||||||
|
|
||||||
printf("expand_table_rows()\n");
|
|
||||||
expand_table_rows();
|
|
||||||
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
|
||||||
print_table();
|
|
||||||
|
|
||||||
|
printf("expand_table_rows()\n");
|
||||||
|
expand_table_rows();
|
||||||
|
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
|
||||||
|
print_table();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user