]> git.sur5r.net Git - i3/i3/commitdiff
Merge branch 'master' into next
authorMichael Stapelberg <michael@stapelberg.de>
Thu, 22 Sep 2011 19:11:44 +0000 (20:11 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Thu, 22 Sep 2011 19:11:44 +0000 (20:11 +0100)
1  2 
src/cmdparse.y
src/floating.c
src/handlers.c
src/randr.c
src/tree.c
src/workspace.c

diff --combined src/cmdparse.y
index 0a99c224d5b64c6fe19187d6dd8e18e92b51daec,bf2fde961c46876bf92135da72bbf6b4cb4e8869..04e8b3ca3f4cb0a8f66337a2132b5e2ceb90223f
@@@ -149,7 -149,6 +149,7 @@@ bool definitelyGreaterThan(float a, flo
  %token              TOK_ENABLE          "enable"
  %token              TOK_DISABLE         "disable"
  %token              TOK_WORKSPACE       "workspace"
 +%token              TOK_OUTPUT          "output"
  %token              TOK_TOGGLE          "toggle"
  %token              TOK_FOCUS           "focus"
  %token              TOK_MOVE            "move"
  
  %token              TOK_CLASS           "class"
  %token              TOK_INSTANCE        "instance"
 +%token              TOK_WINDOW_ROLE     "window_role"
  %token              TOK_ID              "id"
  %token              TOK_CON_ID          "con_id"
  %token              TOK_TITLE           "title"
@@@ -268,9 -266,10 +268,9 @@@ matchend
  
                  }
              } else if (current_match.mark != NULL && current->con->mark != NULL &&
 -                    strcasecmp(current_match.mark, current->con->mark) == 0) {
 +                       regex_matches(current_match.mark, current->con->mark)) {
                  printf("match by mark\n");
 -                    TAILQ_INSERT_TAIL(&owindows, current, owindows);
 -
 +                TAILQ_INSERT_TAIL(&owindows, current, owindows);
              } else {
                  if (current->con->window == NULL)
                      continue;
@@@ -300,20 -299,12 +300,20 @@@ criterion
      TOK_CLASS '=' STR
      {
          printf("criteria: class = %s\n", $3);
 -        current_match.class = $3;
 +        current_match.class = regex_new($3);
 +        free($3);
      }
      | TOK_INSTANCE '=' STR
      {
          printf("criteria: instance = %s\n", $3);
 -        current_match.instance = $3;
 +        current_match.instance = regex_new($3);
 +        free($3);
 +    }
 +    | TOK_WINDOW_ROLE '=' STR
 +    {
 +        printf("criteria: window_role = %s\n", $3);
 +        current_match.role = regex_new($3);
 +        free($3);
      }
      | TOK_CON_ID '=' STR
      {
      | TOK_MARK '=' STR
      {
          printf("criteria: mark = %s\n", $3);
 -        current_match.mark = $3;
 +        current_match.mark = regex_new($3);
 +        free($3);
      }
      | TOK_TITLE '=' STR
      {
          printf("criteria: title = %s\n", $3);
 -        current_match.title = $3;
 +        current_match.title = regex_new($3);
 +        free($3);
      }
      ;
  
@@@ -544,7 -533,7 +544,7 @@@ kill
          else {
              TAILQ_FOREACH(current, &owindows, owindows) {
                  printf("matching: %p / %s\n", current->con, current->con->name);
-                 tree_close(current->con, $2, false);
+                 tree_close(current->con, $2, false, false);
              }
          }
  
@@@ -715,51 -704,6 +715,51 @@@ move
  
          tree_render();
      }
 +    | TOK_MOVE TOK_OUTPUT STR
 +    {
 +        owindow *current;
 +
 +        printf("should move window to output %s", $3);
 +
 +        HANDLE_EMPTY_MATCH;
 +
 +        /* get the output */
 +        Output *current_output = NULL;
 +        Output *output;
 +
 +        TAILQ_FOREACH(current, &owindows, owindows)
 +            current_output = get_output_containing(current->con->rect.x, current->con->rect.y);
 +
 +        assert(current_output != NULL);
 +
 +        if (strcasecmp($3, "up") == 0)
 +            output = get_output_next(D_UP, current_output);
 +        else if (strcasecmp($3, "down") == 0)
 +            output = get_output_next(D_DOWN, current_output);
 +        else if (strcasecmp($3, "left") == 0)
 +            output = get_output_next(D_LEFT, current_output);
 +        else if (strcasecmp($3, "right") == 0)
 +            output = get_output_next(D_RIGHT, current_output);
 +        else
 +            output = get_output_by_name($3);
 +        free($3);
 +
 +        if (!output)
 +            break;
 +
 +        /* get visible workspace on output */
 +        Con *ws = NULL;
 +        GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
 +        if (!ws)
 +            break;
 +
 +        TAILQ_FOREACH(current, &owindows, owindows) {
 +            printf("matching: %p / %s\n", current->con, current->con->name);
 +            con_move_to_workspace(current->con, ws, true, false);
 +        }
 +
 +        tree_render();
 +    }
      ;
  
  append_layout:
@@@ -867,17 -811,6 +867,17 @@@ resize
              double percentage = 1.0 / children;
              LOG("default percentage = %f\n", percentage);
  
 +            orientation_t orientation = current->parent->orientation;
 +
 +            if ((orientation == HORIZ &&
 +                 (direction == TOK_UP || direction == TOK_DOWN)) ||
 +                (orientation == VERT &&
 +                 (direction == TOK_LEFT || direction == TOK_RIGHT))) {
 +                LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
 +                    (orientation == HORIZ ? "horizontal" : "vertical"));
 +                break;
 +            }
 +
              if (direction == TOK_UP || direction == TOK_LEFT) {
                  other = TAILQ_PREV(current, nodes_head, nodes);
              } else {
              }
              if (other == TAILQ_END(workspaces)) {
                  LOG("No other container in this direction found, cannot resize.\n");
 -                return 0;
 +                break;
              }
              LOG("other->percent = %f\n", other->percent);
              LOG("current->percent before = %f\n", current->percent);
diff --combined src/floating.c
index e225b8a6843820793e8976fbe37e13d3c13bd22f,b898d7bc6c901823191dc6a676f5681545aa48d1..e43f4703fa4d8ad7876f7500880bd90e26e271f1
@@@ -91,7 -91,7 +91,7 @@@ void floating_enable(Con *con, bool aut
      /* check if the parent container is empty and close it if so */
      if ((con->parent->type == CT_CON || con->parent->type == CT_FLOATING_CON) && con_num_children(con->parent) == 0) {
          DLOG("Old container empty after setting this child to floating, closing\n");
-         tree_close(con->parent, DONT_KILL_WINDOW, false);
+         tree_close(con->parent, DONT_KILL_WINDOW, false, false);
      }
  
      char *name;
      con->percent = 1.0;
      con->floating = FLOATING_USER_ON;
  
 +    /* 4: set the border style as specified with new_float */
 +    if (automatic)
 +        con->border_style = config.default_floating_border;
 +
      TAILQ_INSERT_TAIL(&(nc->nodes_head), con, nodes);
      TAILQ_INSERT_TAIL(&(nc->focus_head), con, focused);
  
@@@ -216,7 -212,7 +216,7 @@@ void floating_disable(Con *con, bool au
      /* 2: kill parent container */
      TAILQ_REMOVE(&(con->parent->parent->floating_head), con->parent, floating_windows);
      TAILQ_REMOVE(&(con->parent->parent->focus_head), con->parent, focused);
-     tree_close(con->parent, DONT_KILL_WINDOW, false);
+     tree_close(con->parent, DONT_KILL_WINDOW, false, false);
  
      /* 3: re-attach to the parent of the currently focused con on the workspace
       * this floating con was on */
@@@ -520,6 -516,31 +520,6 @@@ void drag_pointer(Con *con, xcb_button_
  }
  
  #if 0
 -/*
 - * Changes focus in the given direction for floating clients.
 - *
 - * Changing to the left/right means going to the previous/next floating client,
 - * changing to top/bottom means cycling through the Z-index.
 - *
 - */
 -void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused, direction_t direction) {
 -        DLOG("floating focus\n");
 -
 -        if (direction == D_LEFT || direction == D_RIGHT) {
 -                /* Go to the next/previous floating client */
 -                Client *client;
 -
 -                while ((client = (direction == D_LEFT ? TAILQ_PREV(currently_focused, floating_clients_head, floating_clients) :
 -                                                        TAILQ_NEXT(currently_focused, floating_clients))) !=
 -                       TAILQ_END(&(currently_focused->workspace->floating_clients))) {
 -                        if (!client->floating)
 -                                continue;
 -                        set_focus(conn, client, true);
 -                        return;
 -                }
 -        }
 -}
 -
  /*
   * Moves the client 10px to the specified direction.
   *
diff --combined src/handlers.c
index 36cf039fdc3bcb600ee7e682ae152f92471c4bfa,336a491f67f6b27300c6cff50226136e9ea3abc6..267159ecf515a7bb0a59b52b388066df1a96e1c7
@@@ -457,7 -457,7 +457,7 @@@ static int handle_unmap_notify_event(xc
          return 1;
      }
  
-     tree_close(con, DONT_KILL_WINDOW, false);
+     tree_close(con, DONT_KILL_WINDOW, false, false);
      tree_render();
      x_push_changes(croot);
      return 1;
@@@ -557,21 -557,6 +557,21 @@@ static bool handle_windowname_change_le
      return true;
  }
  
 +/*
 + * Called when a window changes its WM_WINDOW_ROLE.
 + *
 + */
 +static bool handle_windowrole_change(void *data, xcb_connection_t *conn, uint8_t state,
 +                                     xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
 +    Con *con;
 +    if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
 +        return false;
 +
 +    window_update_role(con->window, prop, false);
 +
 +    return true;
 +}
 +
  #if 0
  /*
   * Updates the client’s WM_CLASS property
@@@ -948,8 -933,7 +948,8 @@@ static struct property_handler_t proper
      { 0, 128, handle_windowname_change_legacy },
      { 0, UINT_MAX, handle_normal_hints },
      { 0, UINT_MAX, handle_clientleader_change },
 -    { 0, UINT_MAX, handle_transient_for }
 +    { 0, UINT_MAX, handle_transient_for },
 +    { 0, 128, handle_windowrole_change }
  };
  #define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
  
@@@ -965,7 -949,6 +965,7 @@@ void property_handlers_init() 
      property_handlers[3].atom = XCB_ATOM_WM_NORMAL_HINTS;
      property_handlers[4].atom = A_WM_CLIENT_LEADER;
      property_handlers[5].atom = XCB_ATOM_WM_TRANSIENT_FOR;
 +    property_handlers[6].atom = A_WM_WINDOW_ROLE;
  }
  
  static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
diff --combined src/randr.c
index dd30925b9301c654132105bda8a23f325e452203,6da90070589d18b33e2aacbd79b7b8b71a3935ce..2b8757e5c25dc674647df2728d5f0fb1b1c1f352
@@@ -447,12 -447,10 +447,12 @@@ void init_ws_for_output(Output *output
          if (!exists) {
              /* Set ->num to the number of the workspace, if the name actually
               * is a number or starts with a number */
 -            long parsed_num = strtol(ws->name, NULL, 10);
 +            char *endptr = NULL;
 +            long parsed_num = strtol(ws->name, &endptr, 10);
              if (parsed_num == LONG_MIN ||
                  parsed_num == LONG_MAX ||
 -                parsed_num <= 0)
 +                parsed_num < 0 ||
 +                endptr == ws->name)
                  ws->num = -1;
              else ws->num = parsed_num;
              LOG("Used number %d for workspace with name %s\n", ws->num, ws->name);
@@@ -791,7 -789,7 +791,7 @@@ void randr_query_outputs() 
                  }
  
                  DLOG("destroying disappearing con %p\n", output->con);
-                 tree_close(output->con, DONT_KILL_WINDOW, true);
+                 tree_close(output->con, DONT_KILL_WINDOW, true, false);
                  DLOG("Done. Should be fine now\n");
                  output->con = NULL;
              }
diff --combined src/tree.c
index e688030f77281f9289c384270f406f0ff81e41c4,76530d604bb1f3546abe89695ab141cbf5abfa6e..4baba58eed118118a85d99818c901ac6c603942d
@@@ -114,8 -114,15 +114,15 @@@ static bool _is_con_mapped(Con *con) 
   * Returns true if the container was killed or false if just WM_DELETE was sent
   * and the window is expected to kill itself.
   *
+  * The dont_kill_parent flag is specified when the function calls itself
+  * recursively while deleting a containers children.
+  *
+  * The force_set_focus flag is specified in the case of killing a floating
+  * window: tree_close() will be invoked for the CT_FLOATINGCON (the parent
+  * container) and focus should be set there.
+  *
   */
- bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent) {
+ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool force_set_focus) {
      bool was_mapped = con->mapped;
      Con *parent = con->parent;
  
      for (child = TAILQ_FIRST(&(con->nodes_head)); child; ) {
          nextchild = TAILQ_NEXT(child, nodes);
          DLOG("killing child=%p\n", child);
-         if (!tree_close(child, kill_window, true))
+         if (!tree_close(child, kill_window, true, false))
              abort_kill = true;
          child = nextchild;
      }
      if (con_is_floating(con)) {
          Con *ws = con_get_workspace(con);
          DLOG("Container was floating, killing floating container\n");
-         tree_close(parent, DONT_KILL_WINDOW, false);
+         tree_close(parent, DONT_KILL_WINDOW, false, (con == focused));
          DLOG("parent container killed\n");
          if (con == focused) {
              DLOG("This is the focused container, i need to find another one to focus. I start looking at ws = %p\n", ws);
                  /* Instead of focusing the dockarea, we need to restore focus to the workspace */
                  con_focus(con_descend_focused(output_get_content(next->parent)));
              } else {
-                 if (con != focused)
+                 if (!force_set_focus && con != focused)
                      DLOG("not changing focus, the container was not focused before\n");
                  else con_focus(next);
              }
@@@ -259,7 -266,7 +266,7 @@@ void tree_close_con(kill_window_t kill_
      assert(focused->type != CT_ROOT);
  
      /* Kill con */
-     tree_close(focused, kill_window, false);
+     tree_close(focused, kill_window, false, false);
  }
  
  /*
@@@ -422,35 -429,12 +429,35 @@@ static bool _tree_next(Con *con, char w
          return true;
      }
  
 +    Con *parent = con->parent;
 +
      if (con->type == CT_FLOATING_CON) {
 -        /* TODO: implement focus for floating windows */
 -        return false;
 -    }
 +        /* left/right focuses the previous/next floating container */
 +        if (orientation == HORIZ) {
 +            Con *next;
 +            if (way == 'n')
 +                next = TAILQ_NEXT(con, floating_windows);
 +            else next = TAILQ_PREV(con, floating_head, floating_windows);
 +
 +            /* If there is no next/previous container, wrap */
 +            if (!next) {
 +                if (way == 'n')
 +                    next = TAILQ_FIRST(&(parent->floating_head));
 +                else next = TAILQ_LAST(&(parent->floating_head), floating_head);
 +            }
  
 -    Con *parent = con->parent;
 +            /* Still no next/previous container? bail out */
 +            if (!next)
 +                return false;
 +
 +            con_focus(con_descend_focused(next));
 +            return true;
 +        } else {
 +            /* up/down cycles through the Z-index */
 +            /* TODO: implement cycling through the z-index */
 +            return false;
 +        }
 +    }
  
      /* If the orientation does not match or there is no other con to focus, we
       * need to go higher in the hierarchy */
@@@ -572,7 -556,7 +579,7 @@@ void tree_flatten(Con *con) 
  
      /* 4: close the redundant cons */
      DLOG("closing redundant cons\n");
-     tree_close(con, DONT_KILL_WINDOW, true);
+     tree_close(con, DONT_KILL_WINDOW, true, false);
  
      /* Well, we got to abort the recursion here because we destroyed the
       * container. However, if tree_flatten() is called sufficiently often,
diff --combined src/workspace.c
index 27899a3781656ce61b301b217704aef3f11c2f8e,a7a5a7aad6b551b717c3408861d4f0aa0d5a190f..325644598453e98b337f756ccd988fd21dbb3223
@@@ -49,12 -49,12 +49,12 @@@ Con *workspace_get(const char *num, boo
          workspace->name = sstrdup(num);
          /* We set ->num to the number if this workspace’s name consists only of
           * a positive number. Otherwise it’s a named ws and num will be -1. */
 -        char *end;
 -        long parsed_num = strtol(num, &end, 10);
 +        char *endptr = NULL;
 +        long parsed_num = strtol(num, &endptr, 10);
          if (parsed_num == LONG_MIN ||
              parsed_num == LONG_MAX ||
              parsed_num < 0 ||
 -            (end && *end != '\0'))
 +            endptr == num)
              workspace->num = -1;
          else workspace->num = parsed_num;
          LOG("num = %d\n", workspace->num);
@@@ -211,7 -211,7 +211,7 @@@ void workspace_show(const char *num) 
          /* check if this workspace is currently visible */
          if (!workspace_is_visible(old)) {
              LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name);
-             tree_close(old, DONT_KILL_WINDOW, false);
+             tree_close(old, DONT_KILL_WINDOW, false, false);
              ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
              changed_num_workspaces = true;
          }