Added Unicode-Support
This commit is contained in:
parent
7d7867acce
commit
1daa395a77
|
@ -22,5 +22,6 @@ struct rect_t {
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
#include "ucs2_to_utf8.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@ SLIST_HEAD(outputs_head, i3_output);
|
||||||
struct outputs_head *outputs;
|
struct outputs_head *outputs;
|
||||||
|
|
||||||
void parse_outputs_json(char* json);
|
void parse_outputs_json(char* json);
|
||||||
|
void init_outputs();
|
||||||
void free_outputs();
|
void free_outputs();
|
||||||
i3_output* get_output_by_name(char* name);
|
i3_output* get_output_by_name(char* name);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
char *convert_utf8_to_ucs2(char *input, int *real_strlen);
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef WORKSPACES_H_
|
#ifndef WORKSPACES_H_
|
||||||
#define WORKSPACES_H_
|
#define WORKSPACES_H_
|
||||||
|
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
typedef struct i3_ws i3_ws;
|
typedef struct i3_ws i3_ws;
|
||||||
|
@ -13,6 +15,8 @@ void free_workspaces();
|
||||||
struct i3_ws {
|
struct i3_ws {
|
||||||
int num;
|
int num;
|
||||||
char *name;
|
char *name;
|
||||||
|
xcb_char2b_t *ucs2_name;
|
||||||
|
int name_glyphs;
|
||||||
int name_width;
|
int name_width;
|
||||||
bool visible;
|
bool visible;
|
||||||
bool focused;
|
bool focused;
|
||||||
|
|
|
@ -7,8 +7,8 @@ void init_xcb();
|
||||||
void clean_xcb();
|
void clean_xcb();
|
||||||
void get_atoms();
|
void get_atoms();
|
||||||
void destroy_windows();
|
void destroy_windows();
|
||||||
void create_windows();
|
void reconfig_windows();
|
||||||
void draw_bars();
|
void draw_bars();
|
||||||
int get_string_width(char *string);
|
int get_string_width(xcb_char2b_t *string, int glyph_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -81,7 +81,7 @@ void child_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
||||||
strip_dzen_formats(buffer);
|
strip_dzen_formats(buffer);
|
||||||
FREE(statusline);
|
FREE(statusline);
|
||||||
statusline = buffer;
|
statusline = buffer;
|
||||||
printf("%s", buffer);
|
printf("%s\n", buffer);
|
||||||
draw_bars();
|
draw_bars();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,45 +91,52 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_child(char *command) {
|
void start_child(char *command) {
|
||||||
int fd[2];
|
child_pid = 0;
|
||||||
pipe(fd);
|
if (command != NULL) {
|
||||||
child_pid = fork();
|
int fd[2];
|
||||||
switch (child_pid) {
|
pipe(fd);
|
||||||
case -1:
|
child_pid = fork();
|
||||||
printf("ERROR: Couldn't fork()");
|
switch (child_pid) {
|
||||||
exit(EXIT_FAILURE);
|
case -1:
|
||||||
case 0:
|
printf("ERROR: Couldn't fork()");
|
||||||
close(fd[0]);
|
exit(EXIT_FAILURE);
|
||||||
|
case 0:
|
||||||
|
close(fd[0]);
|
||||||
|
|
||||||
dup2(fd[1], STDOUT_FILENO);
|
dup2(fd[1], STDOUT_FILENO);
|
||||||
|
|
||||||
static const char *shell = NULL;
|
static const char *shell = NULL;
|
||||||
|
|
||||||
if ((shell = getenv("SHELL")) == NULL)
|
if ((shell = getenv("SHELL")) == NULL)
|
||||||
shell = "/bin/sh";
|
shell = "/bin/sh";
|
||||||
|
|
||||||
execl(shell, shell, "-c", command, (char*) NULL);
|
execl(shell, shell, "-c", command, (char*) NULL);
|
||||||
break;
|
return;
|
||||||
default:
|
default:
|
||||||
close(fd[1]);
|
close(fd[1]);
|
||||||
|
|
||||||
dup2(fd[0], STDIN_FILENO);
|
dup2(fd[0], STDIN_FILENO);
|
||||||
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
child_io = malloc(sizeof(ev_io));
|
break;
|
||||||
ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ);
|
}
|
||||||
ev_io_start(main_loop, child_io);
|
|
||||||
|
|
||||||
/* We must cleanup, if the child unexpectedly terminates */
|
|
||||||
child_sig = malloc(sizeof(ev_io));
|
|
||||||
ev_child_init(child_sig, &child_sig_cb, child_pid, 0);
|
|
||||||
ev_child_start(main_loop, child_sig);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
child_io = malloc(sizeof(ev_io));
|
||||||
|
ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ);
|
||||||
|
ev_io_start(main_loop, child_io);
|
||||||
|
|
||||||
|
/* We must cleanup, if the child unexpectedly terminates */
|
||||||
|
child_sig = malloc(sizeof(ev_io));
|
||||||
|
ev_child_init(child_sig, &child_sig_cb, child_pid, 0);
|
||||||
|
ev_child_start(main_loop, child_sig);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kill_child() {
|
void kill_child() {
|
||||||
kill(child_pid, SIGQUIT);
|
if (child_pid != 0) {
|
||||||
|
kill(child_pid, SIGQUIT);
|
||||||
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,10 @@ void got_subscribe_reply(char *reply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void got_output_reply(char *reply) {
|
void got_output_reply(char *reply) {
|
||||||
printf("Got Outputs-Data!\nDestroying Windows...\n");
|
printf("Parsing Outputs-JSON...\n");
|
||||||
destroy_windows();
|
|
||||||
printf("Parsing JSON...\n");
|
|
||||||
parse_outputs_json(reply);
|
parse_outputs_json(reply);
|
||||||
printf("Creating_Windows...\n");
|
printf("Reconfiguring Windows...\n");
|
||||||
create_windows();
|
reconfig_windows();
|
||||||
}
|
}
|
||||||
|
|
||||||
handler_t reply_handlers[] = {
|
handler_t reply_handlers[] = {
|
||||||
|
|
|
@ -5,21 +5,73 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ev.h>
|
#include <ev.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
char *i3_default_sock_path = "/home/mero/.i3/ipc.sock";
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
int opt;
|
||||||
|
int option_index = 0;
|
||||||
|
char *socket_path = NULL;
|
||||||
|
char *command = NULL;
|
||||||
|
char *fontname = NULL;
|
||||||
|
|
||||||
|
static struct option long_opt[] = {
|
||||||
|
{ "socket", required_argument, 0, 's' },
|
||||||
|
{ "command", required_argument, 0, 'c' },
|
||||||
|
{ "font", required_argument, 0, 'f' },
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ NULL, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((opt = getopt_long(argc, argv, "s:c:f:h", long_opt, &option_index)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 's':
|
||||||
|
socket_path = malloc(strlen(optarg));
|
||||||
|
strcpy(socket_path, optarg);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
command = malloc(strlen(optarg));
|
||||||
|
strcpy(command, optarg);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
fontname = malloc(strlen(optarg));
|
||||||
|
strcpy(socket_path, optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-s socket_path] [-c command] [-f font] [-h]\n", argv[0]);
|
||||||
|
printf("-s <socket_path>: Connect to i3 via <socket_path>\n");
|
||||||
|
printf("-c <command>: Execute <command> to get sdtin\n");
|
||||||
|
printf("-f <font>: Use X-Core-Font <font> for display\n");
|
||||||
|
printf("-h: Display this help-message and exit\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fontname == NULL) {
|
||||||
|
fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_path == NULL) {
|
||||||
|
printf("No Socket Path Specified, default to %s\n", i3_default_sock_path);
|
||||||
|
socket_path = i3_default_sock_path;
|
||||||
|
}
|
||||||
|
|
||||||
main_loop = ev_default_loop(0);
|
main_loop = ev_default_loop(0);
|
||||||
|
|
||||||
init_xcb();
|
init_xcb(fontname);
|
||||||
init_connection("/home/mero/.i3/ipc.sock");
|
init_outputs();
|
||||||
|
init_connection(socket_path);
|
||||||
|
|
||||||
subscribe_events();
|
subscribe_events();
|
||||||
|
|
||||||
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
|
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
|
||||||
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
|
i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
|
||||||
|
|
||||||
start_child("i3status");
|
start_child(command);
|
||||||
|
|
||||||
ev_loop(main_loop, 0);
|
ev_loop(main_loop, 0);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct outputs_json_params {
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
char *json;
|
char *json;
|
||||||
|
bool init;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int outputs_null_cb(void *params_) {
|
static int outputs_null_cb(void *params_) {
|
||||||
|
@ -82,9 +83,11 @@ static int outputs_string_cb(void *params_, const unsigned char *val, unsigned i
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
params->outputs_walk->name = malloc(sizeof(const unsigned char) * (len + 1));
|
char *name = malloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(params->outputs_walk->name, (const char*) val, len);
|
strncpy(name, (const char*) val, len);
|
||||||
params->outputs_walk->name[len] = '\0';
|
name[len] = '\0';
|
||||||
|
|
||||||
|
params->outputs_walk->name = name;
|
||||||
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
|
@ -105,9 +108,7 @@ static int outputs_start_map_cb(void *params_) {
|
||||||
new_output->workspaces = malloc(sizeof(struct ws_head));
|
new_output->workspaces = malloc(sizeof(struct ws_head));
|
||||||
TAILQ_INIT(new_output->workspaces);
|
TAILQ_INIT(new_output->workspaces);
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(params->outputs, new_output, slist);
|
params->outputs_walk = new_output;
|
||||||
|
|
||||||
params->outputs_walk = SLIST_FIRST(params->outputs);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +116,20 @@ static int outputs_start_map_cb(void *params_) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int outputs_end_map_cb(void *params_) {
|
||||||
|
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
||||||
|
|
||||||
|
i3_output *target = get_output_by_name(params->outputs_walk->name);
|
||||||
|
|
||||||
|
if (target == NULL) {
|
||||||
|
SLIST_INSERT_HEAD(outputs, params->outputs_walk, slist);
|
||||||
|
} else {
|
||||||
|
target->ws = params->outputs_walk->ws;
|
||||||
|
target->rect = params->outputs_walk->rect;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) {
|
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int 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);
|
||||||
|
@ -135,18 +150,18 @@ yajl_callbacks outputs_callbacks = {
|
||||||
&outputs_string_cb,
|
&outputs_string_cb,
|
||||||
&outputs_start_map_cb,
|
&outputs_start_map_cb,
|
||||||
&outputs_map_key_cb,
|
&outputs_map_key_cb,
|
||||||
NULL,
|
&outputs_end_map_cb,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void init_outputs() {
|
||||||
|
outputs = malloc(sizeof(struct outputs_head));
|
||||||
|
SLIST_INIT(outputs);
|
||||||
|
}
|
||||||
|
|
||||||
void parse_outputs_json(char *json) {
|
void parse_outputs_json(char *json) {
|
||||||
/* FIXME: Fasciliate stream-processing, i.e. allow starting to interpret
|
|
||||||
* JSON in chunks */
|
|
||||||
struct outputs_json_params params;
|
struct outputs_json_params params;
|
||||||
printf(json);
|
|
||||||
params.outputs = malloc(sizeof(struct outputs_head));
|
|
||||||
SLIST_INIT(params.outputs);
|
|
||||||
|
|
||||||
params.outputs_walk = NULL;
|
params.outputs_walk = NULL;
|
||||||
params.cur_key = NULL;
|
params.cur_key = NULL;
|
||||||
|
@ -173,16 +188,13 @@ void parse_outputs_json(char *json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
yajl_free(handle);
|
yajl_free(handle);
|
||||||
|
|
||||||
if (outputs != NULL) {
|
|
||||||
FREE_SLIST(outputs, i3_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs = params.outputs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i3_output *get_output_by_name(char *name) {
|
i3_output *get_output_by_name(char *name) {
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
|
if (name == 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;
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* vim:ts=8:expandtab
|
||||||
|
*
|
||||||
|
* i3 - an improved dynamic tiling window manager
|
||||||
|
*
|
||||||
|
* © 2009 Michael Stapelberg and contributors
|
||||||
|
*
|
||||||
|
* See file LICENSE for license information.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
static iconv_t conversion_descriptor = 0;
|
||||||
|
static iconv_t conversion_descriptor2 = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the input string, but converted from UCS-2 to UTF-8. Memory will be
|
||||||
|
* allocated, thus the caller has to free the output.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *convert_ucs_to_utf8(char *input) {
|
||||||
|
size_t input_size = 2;
|
||||||
|
/* UTF-8 may consume up to 4 byte */
|
||||||
|
int buffer_size = 8;
|
||||||
|
|
||||||
|
char *buffer = calloc(buffer_size, 1);
|
||||||
|
if (buffer == NULL)
|
||||||
|
err(EXIT_FAILURE, "malloc() failed\n");
|
||||||
|
size_t output_size = buffer_size;
|
||||||
|
/* We need to use an additional pointer, because iconv() modifies it */
|
||||||
|
char *output = buffer;
|
||||||
|
|
||||||
|
/* We convert the input into UCS-2 big endian */
|
||||||
|
if (conversion_descriptor == 0) {
|
||||||
|
conversion_descriptor = iconv_open("UTF-8", "UCS-2BE");
|
||||||
|
if (conversion_descriptor == 0) {
|
||||||
|
fprintf(stderr, "error opening the conversion context\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the conversion descriptor back to original state */
|
||||||
|
iconv(conversion_descriptor, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Convert our text */
|
||||||
|
int rc = iconv(conversion_descriptor, (void*)&input, &input_size, &output, &output_size);
|
||||||
|
if (rc == (size_t)-1) {
|
||||||
|
perror("Converting to UCS-2 failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts the given string to UCS-2 big endian for use with
|
||||||
|
* xcb_image_text_16(). The amount of real glyphs is stored in real_strlen,
|
||||||
|
* a buffer containing the UCS-2 encoded string (16 bit per glyph) is
|
||||||
|
* returned. It has to be freed when done.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *convert_utf8_to_ucs2(char *input, int *real_strlen) {
|
||||||
|
size_t input_size = strlen(input) + 1;
|
||||||
|
/* UCS-2 consumes exactly two bytes for each glyph */
|
||||||
|
int buffer_size = input_size * 2;
|
||||||
|
|
||||||
|
char *buffer = malloc(buffer_size);
|
||||||
|
if (buffer == NULL)
|
||||||
|
err(EXIT_FAILURE, "malloc() failed\n");
|
||||||
|
size_t output_size = buffer_size;
|
||||||
|
/* We need to use an additional pointer, because iconv() modifies it */
|
||||||
|
char *output = buffer;
|
||||||
|
|
||||||
|
/* We convert the input into UCS-2 big endian */
|
||||||
|
if (conversion_descriptor2 == 0) {
|
||||||
|
conversion_descriptor2 = iconv_open("UCS-2BE", "UTF-8");
|
||||||
|
if (conversion_descriptor2 == 0) {
|
||||||
|
fprintf(stderr, "error opening the conversion context\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the conversion descriptor back to original state */
|
||||||
|
iconv(conversion_descriptor2, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Convert our text */
|
||||||
|
int rc = iconv(conversion_descriptor2, (void*)&input, &input_size, &output, &output_size);
|
||||||
|
if (rc == (size_t)-1) {
|
||||||
|
perror("Converting to UCS-2 failed");
|
||||||
|
if (real_strlen != NULL)
|
||||||
|
*real_strlen = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (real_strlen != NULL)
|
||||||
|
*real_strlen = ((buffer_size - output_size) / 2) - 1;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
|
@ -94,32 +94,38 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne
|
||||||
char *output_name;
|
char *output_name;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "name")) {
|
if (!strcmp(params->cur_key, "name")) {
|
||||||
params->workspaces_walk->name = malloc(sizeof(const unsigned char) * (len + 1));
|
params->workspaces_walk->name = malloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(params->workspaces_walk->name, (const char*) val, len);
|
strncpy(params->workspaces_walk->name, (const char*) val, len);
|
||||||
params->workspaces_walk->name[len] = '\0';
|
params->workspaces_walk->name[len] = '\0';
|
||||||
|
|
||||||
params->workspaces_walk->name_width = get_string_width(params->workspaces_walk->name);
|
int ucs2_len;
|
||||||
|
xcb_char2b_t *ucs2_name = (xcb_char2b_t*) convert_utf8_to_ucs2(params->workspaces_walk->name, &ucs2_len);
|
||||||
|
params->workspaces_walk->ucs2_name = ucs2_name;
|
||||||
|
params->workspaces_walk->name_glyphs = ucs2_len;
|
||||||
|
params->workspaces_walk->name_width = get_string_width(params->workspaces_walk->ucs2_name,
|
||||||
|
params->workspaces_walk->name_glyphs);
|
||||||
|
|
||||||
printf("Got Workspace %s, name_width: %d\n",
|
printf("Got Workspace %s, name_width: %d, glyphs: %d\n",
|
||||||
params->workspaces_walk->name,
|
params->workspaces_walk->name,
|
||||||
params->workspaces_walk->name_width);
|
params->workspaces_walk->name_width,
|
||||||
FREE(params->cur_key);
|
params->workspaces_walk->name_glyphs);
|
||||||
|
FREE(params->cur_key);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "output")) {
|
if (!strcmp(params->cur_key, "output")) {
|
||||||
output_name = malloc(sizeof(const unsigned char) * (len + 1));
|
output_name = malloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(output_name, (const char*) val, len);
|
strncpy(output_name, (const char*) val, len);
|
||||||
output_name[len] = '\0';
|
output_name[len] = '\0';
|
||||||
params->workspaces_walk->output = get_output_by_name(output_name);
|
params->workspaces_walk->output = get_output_by_name(output_name);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
||||||
params->workspaces_walk,
|
params->workspaces_walk,
|
||||||
tailq);
|
tailq);
|
||||||
|
|
||||||
free(output_name);
|
FREE(output_name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -128,7 +134,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne
|
||||||
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;
|
||||||
|
|
||||||
if (params->cur_key == NULL) {
|
if (params->cur_key == NULL) {
|
||||||
new_workspace = malloc(sizeof(i3_ws));
|
new_workspace = malloc(sizeof(i3_ws));
|
||||||
|
|
152
i3bar/src/xcb.c
152
i3bar/src/xcb.c
|
@ -1,4 +1,6 @@
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
#include <xcb/xcb_event.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -26,6 +28,8 @@ ev_prepare *xcb_prep;
|
||||||
ev_check *xcb_chk;
|
ev_check *xcb_chk;
|
||||||
ev_io *xcb_io;
|
ev_io *xcb_io;
|
||||||
|
|
||||||
|
xcb_event_handlers_t xcb_event_handlers;
|
||||||
|
|
||||||
uint32_t get_colorpixel(const char *s) {
|
uint32_t get_colorpixel(const char *s) {
|
||||||
char strings[3][3] = { { s[0], s[1], '\0'} ,
|
char strings[3][3] = { { s[0], s[1], '\0'} ,
|
||||||
{ s[2], s[3], '\0'} ,
|
{ s[2], s[3], '\0'} ,
|
||||||
|
@ -128,14 +132,14 @@ void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
||||||
* Prepare- and Check-Watchers */
|
* Prepare- and Check-Watchers */
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_string_width(char *string) {
|
int get_string_width(xcb_char2b_t *string, int glyph_len) {
|
||||||
xcb_query_text_extents_cookie_t cookie;
|
xcb_query_text_extents_cookie_t cookie;
|
||||||
xcb_query_text_extents_reply_t *reply;
|
xcb_query_text_extents_reply_t *reply;
|
||||||
xcb_generic_error_t *error;
|
xcb_generic_error_t *error;
|
||||||
int width;
|
int width;
|
||||||
|
|
||||||
cookie = xcb_query_text_extents(xcb_connection, xcb_font, strlen(string), (xcb_char2b_t*) string);
|
cookie = xcb_query_text_extents(xcb_connection, xcb_font, glyph_len, string);
|
||||||
if ((reply= xcb_query_text_extents_reply(xcb_connection, cookie, &error)) == NULL) {
|
if ((reply = xcb_query_text_extents_reply(xcb_connection, cookie, &error)) == NULL) {
|
||||||
printf("ERROR: Could not get text extents!");
|
printf("ERROR: Could not get text extents!");
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +149,7 @@ int get_string_width(char *string) {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_xcb() {
|
void init_xcb(char *fontname) {
|
||||||
/* FIXME: xcb_connect leaks Memory */
|
/* FIXME: xcb_connect leaks Memory */
|
||||||
xcb_connection = xcb_connect(NULL, NULL);
|
xcb_connection = xcb_connect(NULL, NULL);
|
||||||
if (xcb_connection_has_error(xcb_connection)) {
|
if (xcb_connection_has_error(xcb_connection)) {
|
||||||
|
@ -162,7 +166,6 @@ void init_xcb() {
|
||||||
xcb_root = xcb_screens->root;
|
xcb_root = xcb_screens->root;
|
||||||
|
|
||||||
xcb_font = xcb_generate_id(xcb_connection);
|
xcb_font = xcb_generate_id(xcb_connection);
|
||||||
char *fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1";
|
|
||||||
xcb_open_font(xcb_connection,
|
xcb_open_font(xcb_connection,
|
||||||
xcb_font,
|
xcb_font,
|
||||||
strlen(fontname),
|
strlen(fontname),
|
||||||
|
@ -219,67 +222,80 @@ void get_atoms() {
|
||||||
printf("Got Atoms\n");
|
printf("Got Atoms\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_windows() {
|
void destroy_window(i3_output *output) {
|
||||||
i3_output *walk;
|
if (output == NULL) {
|
||||||
if (outputs == NULL) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
if (output->bar == XCB_NONE) {
|
||||||
if (walk->bar == XCB_NONE) {
|
return;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
xcb_destroy_window(xcb_connection, walk->bar);
|
|
||||||
walk->bar = XCB_NONE;
|
|
||||||
}
|
}
|
||||||
|
xcb_destroy_window(xcb_connection, output->bar);
|
||||||
|
output->bar = XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_windows() {
|
void reconfig_windows() {
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
uint32_t values[2];
|
uint32_t values[4];
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH(walk, outputs, slist) {
|
||||||
if (!walk->active) {
|
if (!walk->active) {
|
||||||
|
destroy_window(walk);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf("Creating Window for output %s\n", walk->name);
|
if (walk->bar == XCB_NONE) {
|
||||||
|
printf("Creating Window for output %s\n", walk->name);
|
||||||
|
|
||||||
walk->bar = xcb_generate_id(xcb_connection);
|
walk->bar = xcb_generate_id(xcb_connection);
|
||||||
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||||
values[0] = xcb_screens->black_pixel;
|
values[0] = xcb_screens->black_pixel;
|
||||||
values[1] = XCB_EVENT_MASK_EXPOSURE |
|
values[1] = XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS;
|
XCB_EVENT_MASK_BUTTON_PRESS;
|
||||||
xcb_create_window(xcb_connection,
|
xcb_create_window(xcb_connection,
|
||||||
xcb_screens->root_depth,
|
xcb_screens->root_depth,
|
||||||
|
walk->bar,
|
||||||
|
xcb_root,
|
||||||
|
walk->rect.x, walk->rect.y,
|
||||||
|
walk->rect.w, font_height + 6,
|
||||||
|
1,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
xcb_screens->root_visual,
|
||||||
|
mask,
|
||||||
|
values);
|
||||||
|
|
||||||
|
xcb_change_property(xcb_connection,
|
||||||
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
walk->bar,
|
||||||
|
atoms[_NET_WM_WINDOW_TYPE],
|
||||||
|
atoms[ATOM],
|
||||||
|
32,
|
||||||
|
1,
|
||||||
|
(unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
||||||
|
|
||||||
|
walk->bargc = xcb_generate_id(xcb_connection);
|
||||||
|
mask = XCB_GC_FONT;
|
||||||
|
values[0] = xcb_font;
|
||||||
|
xcb_create_gc(xcb_connection,
|
||||||
|
walk->bargc,
|
||||||
walk->bar,
|
walk->bar,
|
||||||
xcb_root,
|
|
||||||
walk->rect.x, walk->rect.y,
|
|
||||||
walk->rect.w, font_height + 6,
|
|
||||||
1,
|
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
||||||
xcb_screens->root_visual,
|
|
||||||
mask,
|
mask,
|
||||||
values);
|
values);
|
||||||
|
|
||||||
xcb_change_property(xcb_connection,
|
xcb_map_window(xcb_connection, walk->bar);
|
||||||
XCB_PROP_MODE_REPLACE,
|
} else {
|
||||||
walk->bar,
|
mask = XCB_CONFIG_WINDOW_X |
|
||||||
atoms[_NET_WM_WINDOW_TYPE],
|
XCB_CONFIG_WINDOW_Y |
|
||||||
atoms[ATOM],
|
XCB_CONFIG_WINDOW_WIDTH |
|
||||||
32,
|
XCB_CONFIG_WINDOW_HEIGHT;
|
||||||
1,
|
values[0] = walk->rect.x;
|
||||||
(unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
values[1] = walk->rect.y;
|
||||||
|
values[2] = walk->rect.w;
|
||||||
walk->bargc = xcb_generate_id(xcb_connection);
|
values[3] = walk->rect.h;
|
||||||
mask = XCB_GC_FONT;
|
xcb_configure_window(xcb_connection,
|
||||||
values[0] = xcb_font;
|
walk->bar,
|
||||||
xcb_create_gc(xcb_connection,
|
mask,
|
||||||
walk->bargc,
|
values);
|
||||||
walk->bar,
|
}
|
||||||
mask,
|
|
||||||
values);
|
|
||||||
|
|
||||||
xcb_map_window(xcb_connection, walk->bar);
|
|
||||||
}
|
}
|
||||||
xcb_flush(xcb_connection);
|
xcb_flush(xcb_connection);
|
||||||
}
|
}
|
||||||
|
@ -294,7 +310,7 @@ void draw_bars() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (outputs_walk->bar == XCB_NONE) {
|
if (outputs_walk->bar == XCB_NONE) {
|
||||||
create_windows();
|
reconfig_windows();
|
||||||
}
|
}
|
||||||
uint32_t color = get_colorpixel("000000");
|
uint32_t color = get_colorpixel("000000");
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
|
@ -319,13 +335,23 @@ void draw_bars() {
|
||||||
XCB_GC_FOREGROUND,
|
XCB_GC_FOREGROUND,
|
||||||
&color);
|
&color);
|
||||||
|
|
||||||
xcb_image_text_8(xcb_connection,
|
int glyph_count;
|
||||||
strlen(statusline),
|
xcb_char2b_t *text = (xcb_char2b_t*) convert_utf8_to_ucs2(statusline, &glyph_count);
|
||||||
outputs_walk->bar,
|
|
||||||
outputs_walk->bargc,
|
xcb_void_cookie_t cookie;
|
||||||
outputs_walk->rect.w - get_string_width(statusline) - 4,
|
cookie = xcb_image_text_16(xcb_connection,
|
||||||
font_height + 1,
|
glyph_count,
|
||||||
statusline);
|
outputs_walk->bar,
|
||||||
|
outputs_walk->bargc,
|
||||||
|
outputs_walk->rect.w - get_string_width(text, glyph_count) - 4,
|
||||||
|
font_height + 1,
|
||||||
|
(xcb_char2b_t*) text);
|
||||||
|
|
||||||
|
xcb_generic_error_t *err = xcb_request_check(xcb_connection, cookie);
|
||||||
|
|
||||||
|
if (err != NULL) {
|
||||||
|
printf("XCB-Error: %d\n", err->error_code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i3_ws *ws_walk;
|
i3_ws *ws_walk;
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
|
@ -357,12 +383,12 @@ void draw_bars() {
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
XCB_GC_FOREGROUND,
|
XCB_GC_FOREGROUND,
|
||||||
&color);
|
&color);
|
||||||
xcb_image_text_8(xcb_connection,
|
xcb_image_text_16(xcb_connection,
|
||||||
strlen(ws_walk->name),
|
ws_walk->name_glyphs,
|
||||||
outputs_walk->bar,
|
outputs_walk->bar,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
i + 5, font_height + 1,
|
i + 5, font_height + 1,
|
||||||
ws_walk->name);
|
ws_walk->ucs2_name);
|
||||||
i += 10 + ws_walk->name_width;
|
i += 10 + ws_walk->name_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue