]> git.sur5r.net Git - i3/i3/commitdiff
Merge pull request #3452 from orestisf1993/title_align
authorIngo Bürk <admin@airblader.de>
Tue, 23 Oct 2018 14:41:54 +0000 (16:41 +0200)
committerGitHub <noreply@github.com>
Tue, 23 Oct 2018 14:41:54 +0000 (16:41 +0200)
Add title_align config directive

1  2 
docs/userguide
include/configuration.h
src/x.c

diff --combined docs/userguide
index 4bfcdb6b980e5a2009bdc6f61541054c6a7b00e1,401d5ff2ee25a07240facf9893fffafc3a21ed98..91060ab2cc6df006f4c23a80665976d0c503041b
@@@ -245,11 -245,9 +245,11 @@@ you open a new terminal, it will open b
  
  So, how can you open a new terminal window to the *right* of the current one?
  The solution is to use +focus parent+, which will focus the +Parent Container+ of
 -the current +Container+. In this case, you would focus the +Vertical Split
 -Container+ which is *inside* the horizontally oriented workspace. Thus, now new
 -windows will be opened to the right of the +Vertical Split Container+:
 +the current +Container+. In default configuration, use +$mod+a+ to navigate one 
 ++Container+ up the tree (you can repeat this multiple times until you get to the
 ++Workspace Container+). In this case, you would focus the +Vertical Split Container+
 +which is *inside* the horizontally oriented workspace. Thus, now new windows will be
 +opened to the right of the +Vertical Split Container+:
  
  image::tree-shot3.png["shot3",title="Focus parent, then open new terminal"]
  
@@@ -587,6 -585,16 +587,16 @@@ workspace_layout default|stacking|tabbe
  workspace_layout tabbed
  ---------------------
  
+ === Window title alignment
+ This option determines the window title's text alignment.
+ Default is +left+
+ *Syntax*:
+ ---------------------------------------------
+ title_align left|center|right
+ ---------------------------------------------
  === Default border style for new windows
  
  This option determines which border style new windows will have. The default is
@@@ -1006,7 -1014,7 +1016,7 @@@ ipc-socket ~/.i3/i3-ipc.soc
  ----------------------------
  
  You can then use the +i3-msg+ application to perform any command listed in
 -the next section.
 +<<list_of_commands>>.
  
  === Focus follows mouse
  
@@@ -1727,7 -1735,6 +1737,7 @@@ bar 
  }
  --------------------------------------
  
 +[[list_of_commands]]
  == List of commands
  
  Commands are what you bind to specific keypresses. You can also issue commands
diff --combined include/configuration.h
index d99d9fff663cd5bc965abd0049f4f24ec2ffd250,a1e9cc8029418d3fa8af098d70fd9bd2f84c71aa..6f55ac2a57f7fe7ef280ca956267b46c63b82db9
@@@ -201,6 -201,13 +201,13 @@@ struct Config 
       * decoration. Marks starting with a "_" will be ignored either way. */
      bool show_marks;
  
+     /** Title alignment options. */
+     enum {
+         ALIGN_LEFT,
+         ALIGN_CENTER,
+         ALIGN_RIGHT
+     } title_align;
      /** The default border style for new windows. */
      border_style_t default_border;
  
@@@ -427,7 -434,7 +434,7 @@@ void ungrab_all_keys(xcb_connection_t *
   * Sends the current bar configuration as an event to all barconfig_update listeners.
   *
   */
 -void update_barconfig();
 +void update_barconfig(void);
  
  /**
   * Kills the configerror i3-nagbar process, if any.
diff --combined src/x.c
index 6a0170a5699be528dd17b67b05cf13396400edc5,ceffd30a446255277b8177bda386c4e312f52f13..0fc6e714e5ab27f28c1ae929ed6849ceb4adbb50
+++ b/src/x.c
@@@ -42,7 -42,7 +42,7 @@@ typedef struct con_state 
      bool child_mapped;
      bool is_hidden;
  
 -    /** The con for which this state is. */
 +    /* The con for which this state is. */
      Con *con;
  
      /* For reparenting, we have a flag (need_reparent) and the X ID of the old
@@@ -504,12 -504,14 +504,12 @@@ void x_draw_decoration(Con *con) 
      /* 3: draw a rectangle in border color around the client */
      if (p->border_style != BS_NONE && p->con_is_leaf) {
          /* We might hide some borders adjacent to the screen-edge */
 -        adjacent_t borders_to_hide = ADJ_NONE;
 -        borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
 -
 +        adjacent_t borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
          Rect br = con_border_style_rect(con);
  
          /* These rectangles represent the border around the child window
           * (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 children are not freely resizable and we want
           * their background color to "shine through". */
          if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) {
              draw_util_rectangle(&(con->frame_buffer), p->color->child_border, 0, 0, br.x, r->height);
          goto after_title;
      }
  
+     const int title_padding = logical_px(2);
+     const int deco_width = (int)con->deco_rect.width;
      int mark_width = 0;
      if (config.show_marks && !TAILQ_EMPTY(&(con->marks_head))) {
          char *formatted_mark = sstrdup("");
              i3String *mark = i3string_from_utf8(formatted_mark);
              mark_width = predict_text_width(mark);
  
+             int mark_offset_x = (config.title_align == ALIGN_RIGHT)
+                                     ? title_padding
+                                     : deco_width - mark_width - title_padding;
              draw_util_text(mark, &(parent->frame_buffer),
                             p->color->text, p->color->background,
-                            con->deco_rect.x + con->deco_rect.width - mark_width - logical_px(2),
+                            con->deco_rect.x + mark_offset_x,
                             con->deco_rect.y + text_offset_y, mark_width);
              I3STRING_FREE(mark);
+             mark_width += title_padding;
          }
  
          FREE(formatted_mark);
          goto copy_pixmaps;
      }
  
+     int title_offset_x;
+     switch (config.title_align) {
+         case ALIGN_LEFT:
+             /* (pad)[text    ](pad)[mark + its pad) */
+             title_offset_x = title_padding;
+             break;
+         case ALIGN_CENTER:
+             /* (pad)[  text  ](pad)[mark + its pad)
+              * To center the text inside its allocated space, the surface
+              * between the brackets, we use the formula
+              * (surface_width - predict_text_width) / 2
+              * where surface_width = deco_width - 2 * pad - mark_width
+              * so, offset = pad + (surface_width - predict_text_width) / 2 =
+              * = … = (deco_width - mark_width - predict_text_width) / 2 */
+             title_offset_x = max(title_padding, (deco_width - mark_width - predict_text_width(title)) / 2);
+             break;
+         case ALIGN_RIGHT:
+             /* [mark + its pad](pad)[    text](pad) */
+             title_offset_x = max(title_padding + mark_width, deco_width - title_padding - predict_text_width(title));
+             break;
+     }
      draw_util_text(title, &(parent->frame_buffer),
                     p->color->text, p->color->background,
-                    con->deco_rect.x + logical_px(2),
+                    con->deco_rect.x + title_offset_x,
                     con->deco_rect.y + text_offset_y,
-                    con->deco_rect.width - mark_width - 2 * logical_px(2));
+                    deco_width - mark_width - 2 * title_padding);
  
      if (con->title_format != NULL) {
          I3STRING_FREE(title);
@@@ -1252,7 -1283,7 +1281,7 @@@ void x_set_name(Con *con, const char *n
   * Set up the I3_SHMLOG_PATH atom.
   *
   */
 -void update_shmlog_atom() {
 +void update_shmlog_atom(void) {
      if (*shmlogname == '\0') {
          xcb_delete_property(conn, root, A_I3_SHMLOG_PATH);
      } else {