Merge pull request #1601 from Airblader/feature-titlebar-marks

Show marks in the titlebar
This commit is contained in:
Michael Stapelberg 2015-03-30 23:53:42 +02:00
commit ebac737314
10 changed files with 70 additions and 5 deletions

View File

@ -1006,6 +1006,24 @@ focus::
none::
The window will neither be focused, nor be marked urgent.
=== Drawing marks on window decoration
If activated, marks on windows are drawn in their window decoration. However,
any mark starting with an underscore in its name (+_+) will not be drawn even if
this option is activated.
The default for this option is +yes+.
*Syntax*:
-------------------
show_marks [yes|no]
-------------------
*Example*:
--------------
show_marks yes
--------------
== Configuring i3bar
The bar at the bottom of your monitor is drawn by a separate process called
@ -1886,6 +1904,8 @@ The additional +--toggle+ option will remove the mark if the window already has
this mark, add it if the window has none or replace the current mark if it has
another mark.
Refer to +show_marks+ if you don't want marks to be shown in the window decoration.
*Syntax*:
------------------------------
mark [--toggle] identifier

View File

@ -179,6 +179,10 @@ struct Config {
FOWA_NONE
} focus_on_window_activation;
/** Specifies whether or not marks should be displayed in the window
* decoration. Marks starting with a "_" will be ignored either way. */
bool show_marks;
/** The default border style for new windows. */
border_style_t default_border;

View File

@ -52,6 +52,7 @@ CFGFUN(force_xinerama, const char *value);
CFGFUN(fake_outputs, const char *outputs);
CFGFUN(force_display_urgency_hint, const long duration_ms);
CFGFUN(focus_on_window_activation, const char *mode);
CFGFUN(show_marks, const char *value);
CFGFUN(hide_edge_borders, const char *borders);
CFGFUN(assign, const char *workspace);
CFGFUN(ipc_socket, const char *path);

View File

@ -543,6 +543,8 @@ struct Con {
/* user-definable mark to jump to this container later */
char *mark;
/* cached to decide whether a redraw is needed */
bool mark_changed;
double percent;

View File

@ -39,6 +39,7 @@ state INITIAL:
'fake_outputs', 'fake-outputs' -> FAKE_OUTPUTS
'force_display_urgency_hint' -> FORCE_DISPLAY_URGENCY_HINT
'focus_on_window_activation' -> FOCUS_ON_WINDOW_ACTIVATION
'show_marks' -> SHOW_MARKS
'workspace' -> WORKSPACE
'ipc_socket', 'ipc-socket' -> IPC_SOCKET
'restart_state' -> RESTART_STATE
@ -205,6 +206,11 @@ state FORCE_DISPLAY_URGENCY_HINT:
duration_ms = number
-> FORCE_DISPLAY_URGENCY_HINT_MS
# show_marks
state SHOW_MARKS:
value = word
-> call cfg_show_marks($value)
state FORCE_DISPLAY_URGENCY_HINT_MS:
'ms'
->

View File

@ -1046,6 +1046,7 @@ void cmd_mark(I3_CMD, char *mark, char *toggle) {
owindow *current;
TAILQ_FOREACH(current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
current->con->mark_changed = true;
if (toggle != NULL && current->con->mark && strcmp(current->con->mark, mark) == 0) {
DLOG("removing window mark %s\n", mark);
FREE(current->con->mark);
@ -1070,8 +1071,10 @@ void cmd_mark(I3_CMD, char *mark, char *toggle) {
if (matched)
continue;
if (con->mark && strcmp(con->mark, mark) == 0)
if (con->mark && strcmp(con->mark, mark) == 0) {
FREE(con->mark);
con->mark_changed = true;
}
}
cmd_output->needs_tree_render = true;
@ -1087,14 +1090,20 @@ void cmd_unmark(I3_CMD, char *mark) {
if (mark == NULL) {
Con *con;
TAILQ_FOREACH(con, &all_cons, all_cons) {
if (con->mark == NULL)
continue;
FREE(con->mark);
con->mark_changed = true;
}
DLOG("removed all window marks");
} else {
Con *con;
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);
con->mark_changed = true;
}
}
DLOG("removed window mark %s\n", mark);
}

View File

@ -190,6 +190,8 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888", "#000000");
INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff", "#000000");
config.show_marks = true;
config.default_border = BS_NORMAL;
config.default_floating_border = BS_NORMAL;
config.default_border_width = logical_px(2);

View File

@ -346,6 +346,10 @@ CFGFUN(focus_on_window_activation, const char *mode) {
DLOG("Set new focus_on_window_activation mode = %i", config.focus_on_window_activation);
}
CFGFUN(show_marks, const char *value) {
config.show_marks = eval_boolstr(value);
}
CFGFUN(workspace, const char *workspace, const char *output) {
DLOG("Assigning workspace \"%s\" to output \"%s\"\n", workspace, output);
/* Check for earlier assignments of the same workspace so that we

21
src/x.c
View File

@ -363,6 +363,7 @@ void x_draw_decoration(Con *con) {
(con->window == NULL || !con->window->name_x_changed) &&
!parent->pixmap_recreated &&
!con->pixmap_recreated &&
!con->mark_changed &&
memcmp(p, con->deco_render_params, sizeof(struct deco_render_params)) == 0) {
free(p);
goto copy_pixmaps;
@ -381,6 +382,7 @@ void x_draw_decoration(Con *con) {
parent->pixmap_recreated = false;
con->pixmap_recreated = false;
con->mark_changed = false;
/* 2: draw the client.background, but only for the parts around the client_rect */
if (con->window != NULL) {
@ -531,10 +533,25 @@ void x_draw_decoration(Con *con) {
//DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult);
int indent_px = (indent_level * 5) * indent_mult;
int mark_width = 0;
if (config.show_marks && con->mark != NULL && (con->mark)[0] != '_') {
char *formatted_mark;
sasprintf(&formatted_mark, "[%s]", con->mark);
i3String *mark = i3string_from_utf8(formatted_mark);
FREE(formatted_mark);
mark_width = predict_text_width(mark);
draw_text(mark, parent->pixmap, parent->pm_gc,
con->deco_rect.x + con->deco_rect.width - mark_width - logical_px(2),
con->deco_rect.y + text_offset_y, mark_width);
I3STRING_FREE(mark);
}
draw_text(win->name,
parent->pixmap, parent->pm_gc,
con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
con->deco_rect.width - 2 - indent_px);
con->deco_rect.x + logical_px(2) + indent_px, con->deco_rect.y + text_offset_y,
con->deco_rect.width - logical_px(2) - indent_px - mark_width - logical_px(2));
after_title:
/* Since we dont clip the text at all, it might in some cases be painted

View File

@ -433,7 +433,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4
EOT
my $expected_all_tokens = <<'EOT';
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
EOT
my $expected_end = <<'EOT';