]> git.sur5r.net Git - i3/i3/commitdiff
Merge branch 'master' into next
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 4 Aug 2012 14:10:37 +0000 (16:10 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 4 Aug 2012 14:10:37 +0000 (16:10 +0200)
1  2 
src/commands.c
src/floating.c
src/randr.c

diff --combined src/commands.c
index a1ef3bbf195d8949d961a3e2f3f5cd12460b2e22,66270f7599fd8e406bd1d5ba93e39d3a73373acf..44e6a23d4533f275b6ddffd15c96dd905c3899ea
@@@ -23,7 -23,7 +23,7 @@@
  } while (0)
  
  /** When the command did not include match criteria (!), we use the currently
 - * focused command. 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
   * every command.
   */
@@@ -351,7 -351,7 +351,7 @@@ void cmd_criteria_add(I3_CMD, char *cty
  
  /*
   * Implementation of 'move [window|container] [to] workspace
 - * next|prev|next_on_output|prev_on_output'.
 + * next|prev|next_on_output|prev_on_output|current'.
   *
   */
  void cmd_move_con_to_workspace(I3_CMD, char *which) {
  
      DLOG("which=%s\n", which);
  
 +    /* We have nothing to move:
 +     *  when criteria was specified but didn't match any window or
 +     *  when criteria wasn't specified and we don't have any window focused. */
 +    if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
 +        (match_is_empty(current_match) && focused->type == CT_WORKSPACE)) {
 +        ysuccess(false);
 +        return;
 +    }
 +
      HANDLE_EMPTY_MATCH;
  
      /* get the workspace */
          ws = workspace_next_on_output();
      else if (strcmp(which, "prev_on_output") == 0)
          ws = workspace_prev_on_output();
 +    else if (strcmp(which, "current") == 0)
 +        ws = con_get_workspace(focused);
      else {
          ELOG("BUG: called with which=%s\n", which);
          ysuccess(false);
@@@ -411,11 -400,9 +411,11 @@@ void cmd_move_con_to_workspace_name(I3_
  
      owindow *current;
  
 -    /* Error out early to not create a non-existing workspace (in
 -     * workspace_get()) if we are not actually able to move anything. */
 -    if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
 +    /* We have nothing to move:
 +     *  when criteria was specified but didn't match any window or
 +     *  when criteria wasn't specified and we don't have any window focused. */
 +    if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
 +        (match_is_empty(current_match) && focused->type == CT_WORKSPACE)) {
          ysuccess(false);
          return;
      }
  void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
      owindow *current;
  
 -    /* Error out early to not create a non-existing workspace (in
 -     * workspace_get()) if we are not actually able to move anything. */
 -    if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
 +    /* We have nothing to move:
 +     *  when criteria was specified but didn't match any window or
 +     *  when criteria wasn't specified and we don't have any window focused. */
 +    if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) ||
 +        (match_is_empty(current_match) && focused->type == CT_WORKSPACE)) {
          ysuccess(false);
          return;
      }
@@@ -519,8 -504,6 +519,8 @@@ static bool cmd_resize_tiling_direction
      LOG("tiling resize\n");
      /* get the appropriate current container (skip stacked/tabbed cons) */
      Con *current = focused;
 +    Con *other = NULL;
 +    double percentage = 0;
      while (current->parent->layout == L_STACKED ||
             current->parent->layout == L_TABBED)
          current = current->parent;
      orientation_t search_orientation =
          (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0 ? HORIZ : VERT);
  
 -    while (current->type != CT_WORKSPACE &&
 -           current->type != CT_FLOATING_CON &&
 -           current->parent->orientation != search_orientation)
 -        current = current->parent;
 +    do {
 +        if (con_orientation(current->parent) != search_orientation) {
 +            current = current->parent;
 +            continue;
 +        }
  
 -    /* get the default percentage */
 -    int children = con_num_children(current->parent);
 -    Con *other;
 -    LOG("ins. %d children\n", children);
 -    double percentage = 1.0 / children;
 -    LOG("default percentage = %f\n", percentage);
 +        /* get the default percentage */
 +        int children = con_num_children(current->parent);
 +        LOG("ins. %d children\n", children);
 +        percentage = 1.0 / children;
 +        LOG("default percentage = %f\n", percentage);
  
 -    orientation_t orientation = current->parent->orientation;
 +        orientation_t orientation = con_orientation(current->parent);
  
 -    if ((orientation == HORIZ &&
 -         (strcmp(direction, "up") == 0 || strcmp(direction, "down") == 0)) ||
 -        (orientation == VERT &&
 -         (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) {
 -        LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
 -            (orientation == HORIZ ? "horizontal" : "vertical"));
 -        ysuccess(false);
 -        return false;
 -    }
 +        if ((orientation == HORIZ &&
 +             (strcmp(direction, "up") == 0 || strcmp(direction, "down") == 0)) ||
 +            (orientation == VERT &&
 +             (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) {
 +            LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
 +                (orientation == HORIZ ? "horizontal" : "vertical"));
 +            ysuccess(false);
 +            return false;
 +        }
  
 -    if (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) {
 -        other = TAILQ_PREV(current, nodes_head, nodes);
 -    } else {
 -        other = TAILQ_NEXT(current, nodes);
 -    }
 -    if (other == TAILQ_END(workspaces)) {
 -        LOG("No other container in this direction found, cannot resize.\n");
 +        if (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) {
 +            other = TAILQ_PREV(current, nodes_head, nodes);
 +        } else {
 +            other = TAILQ_NEXT(current, nodes);
 +        }
 +        if (other == TAILQ_END(workspaces)) {
 +            LOG("No other container in this direction found, trying to look further up in the tree...\n");
 +            current = current->parent;
 +            continue;
 +        }
 +        break;
 +    } while (current->type != CT_WORKSPACE &&
 +             current->type != CT_FLOATING_CON);
 +
 +    if (other == NULL) {
 +        LOG("No other container in this direction found, trying to look further up in the tree...\n");
          ysuccess(false);
          return false;
      }
 +
      LOG("other->percent = %f\n", other->percent);
      LOG("current->percent before = %f\n", current->percent);
      if (current->percent == 0.0)
@@@ -612,7 -585,7 +612,7 @@@ static bool cmd_resize_tiling_width_hei
  
      while (current->type != CT_WORKSPACE &&
             current->type != CT_FLOATING_CON &&
 -           current->parent->orientation != search_orientation)
 +           con_orientation(current->parent) != search_orientation)
          current = current->parent;
  
      /* get the default percentage */
      double percentage = 1.0 / children;
      LOG("default percentage = %f\n", percentage);
  
 -    orientation_t orientation = current->parent->orientation;
 +    orientation_t orientation = con_orientation(current->parent);
  
      if ((orientation == HORIZ &&
           strcmp(direction, "height") == 0) ||
@@@ -1028,9 -1001,14 +1028,14 @@@ void cmd_move_workspace_to_output(I3_CM
      TAILQ_FOREACH(current, &owindows, owindows) {
          Output *current_output = get_output_containing(current->con->rect.x,
                                                         current->con->rect.y);
+         if (!current_output) {
+             ELOG("Cannot get current output. This is a bug in i3.\n");
+             ysuccess(false);
+             return;
+         }
          Output *output = get_output_from_string(current_output, name);
          if (!output) {
-             LOG("No such output\n");
+             ELOG("Could not get output from string \"%s\"\n", name);
              ysuccess(false);
              return;
          }
@@@ -1248,26 -1226,23 +1253,26 @@@ void cmd_focus_window_mode(I3_CMD, cha
   *
   */
  void cmd_focus_level(I3_CMD, char *level) {
 -    if (focused &&
 -        focused->type != CT_WORKSPACE &&
 -        focused->fullscreen_mode != CF_NONE) {
 -        LOG("Cannot change focus while in fullscreen mode.\n");
 -        ysuccess(false);
 -        return;
 -    }
 -
      DLOG("level = %s\n", level);
 +    bool success = false;
 +
 +    /* Focusing the parent can only be allowed if the newly
 +     * focused container won't escape the fullscreen container. */
 +    if (strcmp(level, "parent") == 0) {
 +        if (focused && focused->parent) {
 +            if (con_fullscreen_permits_focusing(focused->parent))
 +                success = level_up();
 +            else
 +                LOG("Currently in fullscreen, not going up\n");
 +        }
 +    }
  
 -    if (strcmp(level, "parent") == 0)
 -        level_up();
 -    else level_down();
 +    /* Focusing a child should always be allowed. */
 +    else success = level_down();
  
 -    cmd_output->needs_tree_render = true;
 +    cmd_output->needs_tree_render = success;
      // XXX: default reply for now, make this a better reply
 -    ysuccess(true);
 +    ysuccess(success);
  }
  
  /*
@@@ -1300,9 -1275,13 +1305,9 @@@ void cmd_focus(I3_CMD) 
          if (!ws)
              continue;
  
 -        /* Don't allow the focus switch if the focused and current
 -         * containers are in the same workspace. */
 -        if (focused &&
 -            focused->type != CT_WORKSPACE &&
 -            focused->fullscreen_mode != CF_NONE &&
 -            con_get_workspace(focused) == ws) {
 -            LOG("Cannot change focus while in fullscreen mode (same workspace).\n");
 +        /* Check the fullscreen focus constraints. */
 +        if (!con_fullscreen_permits_focusing(current->con)) {
 +            LOG("Cannot change focus while in fullscreen mode (fullscreen rules).\n");
              ysuccess(false);
              return;
          }
@@@ -1397,27 -1376,17 +1402,27 @@@ void cmd_move_direction(I3_CMD, char *d
  }
  
  /*
 - * Implementation of 'layout default|stacked|stacking|tabbed'.
 + * Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
   *
   */
  void cmd_layout(I3_CMD, char *layout_str) {
      if (strcmp(layout_str, "stacking") == 0)
          layout_str = "stacked";
 -    DLOG("changing layout to %s\n", layout_str);
      owindow *current;
 -    int layout = (strcmp(layout_str, "default") == 0 ? L_DEFAULT :
 -                  (strcmp(layout_str, "stacked") == 0 ? L_STACKED :
 -                   L_TABBED));
 +    int layout;
 +    /* default is a special case which will be handled in con_set_layout(). */
 +    if (strcmp(layout_str, "default") == 0)
 +        layout = L_DEFAULT;
 +    else if (strcmp(layout_str, "stacked") == 0)
 +        layout = L_STACKED;
 +    else if (strcmp(layout_str, "tabbed") == 0)
 +        layout = L_TABBED;
 +    else if (strcmp(layout_str, "splitv") == 0)
 +        layout = L_SPLITV;
 +    else if (strcmp(layout_str, "splith") == 0)
 +        layout = L_SPLITH;
 +
 +    DLOG("changing layout to %s (%d)\n", layout_str, layout);
  
      /* check if the match is empty, not if the result is empty */
      if (match_is_empty(current_match))
      ysuccess(true);
  }
  
 +/*
 + * Implementation of 'layout toggle [all|split]'.
 + *
 + */
 +void cmd_layout_toggle(I3_CMD, char *toggle_mode) {
 +    owindow *current;
 +
 +    if (toggle_mode == NULL)
 +        toggle_mode = "default";
 +
 +    DLOG("toggling layout (mode = %s)\n", toggle_mode);
 +
 +    /* check if the match is empty, not if the result is empty */
 +    if (match_is_empty(current_match))
 +        con_toggle_layout(focused->parent, toggle_mode);
 +    else {
 +        TAILQ_FOREACH(current, &owindows, owindows) {
 +            DLOG("matching: %p / %s\n", current->con, current->con->name);
 +            con_toggle_layout(current->con, toggle_mode);
 +        }
 +    }
 +
 +    cmd_output->needs_tree_render = true;
 +    // XXX: default reply for now, make this a better reply
 +    ysuccess(true);
 +}
 +
  /*
   * Implementaiton of 'exit'.
   *
   */
  void cmd_exit(I3_CMD) {
      LOG("Exiting due to user command.\n");
 +    xcb_disconnect(conn);
      exit(0);
  
      /* unreached */
  void cmd_reload(I3_CMD) {
      LOG("reloading\n");
      kill_configerror_nagbar(false);
 +    kill_commanderror_nagbar(false);
      load_configuration(conn, NULL, true);
      x_set_i3_atoms();
      /* Send an IPC event just in case the ws names have changed */
@@@ -1509,7 -1449,6 +1514,7 @@@ void cmd_restart(I3_CMD) 
  void cmd_open(I3_CMD) {
      LOG("opening new container\n");
      Con *con = tree_open_con(NULL, NULL);
 +    con->layout = L_SPLITH;
      con_focus(con);
  
      y(map_open);
diff --combined src/floating.c
index 90c4d5607c26ff9fc7c838de77719909b51eb183,b90eac3e3fde78eb1da2ace2796affea5eafd2c7..0bc5f6d65aac466814b08c62350c5c4d6fe18d3b
@@@ -40,7 -40,7 +40,7 @@@ void floating_enable(Con *con, bool aut
      }
  
      /* 1: If the container is a workspace container, we need to create a new
 -     * split-container with the same orientation and make that one floating. We
 +     * split-container with the same layout and make that one floating. We
       * cannot touch the workspace container itself because floating containers
       * are children of the workspace. */
      if (con->type == CT_WORKSPACE) {
@@@ -52,7 -52,7 +52,7 @@@
          /* TODO: refactor this with src/con.c:con_set_layout */
          Con *new = con_new(NULL, NULL);
          new->parent = con;
 -        new->orientation = con->orientation;
 +        new->layout = con->layout;
  
          /* since the new container will be set into floating mode directly
           * afterwards, we need to copy the workspace rect. */
@@@ -97,9 -97,8 +97,9 @@@
       * otherwise. */
      Con *ws = con_get_workspace(con);
      nc->parent = ws;
 -    nc->orientation = NO_ORIENTATION;
 +    nc->split = true;
      nc->type = CT_FLOATING_CON;
 +    nc->layout = L_SPLITH;
      /* We insert nc already, even though its rect is not yet calculated. This
       * is necessary because otherwise the workspace might be empty (and get
       * closed in tree_close()) even though it’s not. */
@@@ -608,19 -607,24 +608,24 @@@ void floating_reposition(Con *con, Rec
   *
   */
  void floating_fix_coordinates(Con *con, Rect *old_rect, Rect *new_rect) {
-     DLOG("Fixing coordinates of floating window %p\n", con);
+     DLOG("Fixing coordinates of floating window %p (rect (%d, %d), %d x %d)\n",
+          con, con->rect.x, con->rect.y, con->rect.width, con->rect.height);
+     DLOG("old_rect = (%d, %d), %d x %d\n",
+          old_rect->x, old_rect->y, old_rect->width, old_rect->height);
+     DLOG("new_rect = (%d, %d), %d x %d\n",
+          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
       * of the output on which the window is on */
-     uint32_t rel_x = (con->rect.x - old_rect->x);
-     uint32_t rel_y = (con->rect.y - old_rect->y);
+     int32_t rel_x = (con->rect.x - old_rect->x);
+     int32_t rel_y = (con->rect.y - old_rect->y);
      /* Then we calculate a fraction, for example 0.63 for a window
       * which is at y = 1212 of a 1920 px high output */
 -    double fraction_x = ((double)rel_x / (int32_t)old_rect->width);
 -    double fraction_y = ((double)rel_y / (int32_t)old_rect->height);
      DLOG("rel_x = %d, rel_y = %d, fraction_x = %f, fraction_y = %f, output->w = %d, output->h = %d\n",
 -         rel_x, rel_y, fraction_x, fraction_y, old_rect->width, old_rect->height);
 -    con->rect.x = (int32_t)new_rect->x + (fraction_x * (int32_t)new_rect->width);
 -    con->rect.y = (int32_t)new_rect->y + (fraction_y * (int32_t)new_rect->height);
 +          rel_x, rel_y, (double)rel_x / old_rect->width, (double)rel_y / 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 */
-     con->rect.x = new_rect->x + (double)(rel_x * new_rect->width)  / old_rect->width;
-     con->rect.y = new_rect->y + (double)(rel_y * new_rect->height) / old_rect->height;
++    con->rect.x = (int32_t)new_rect->x + (double)(rel_x * (int32_t)new_rect->width)  / (int32_t)old_rect->width;
++    con->rect.y = (int32_t)new_rect->y + (double)(rel_y * (int32_t)new_rect->height) / (int32_t)old_rect->height;
      DLOG("Resulting coordinates: x = %d, y = %d\n", con->rect.x, con->rect.y);
  }
  
diff --combined src/randr.c
index f69d15a8cc97a38a329bf48f2c44f8f988e333bb,d29ce12882fdbcfa312e89246fd203e8a9386a18..b691a3326a42640b2b0082399f8efd19310a7d01
@@@ -256,6 -256,7 +256,6 @@@ void output_init_con(Output *output) 
      Con *topdock = con_new(NULL, NULL);
      topdock->type = CT_DOCKAREA;
      topdock->layout = L_DOCKAREA;
 -    topdock->orientation = VERT;
      /* this container swallows dock clients */
      Match *match = scalloc(sizeof(Match));
      match_init(match);
      DLOG("adding main content container\n");
      Con *content = con_new(NULL, NULL);
      content->type = CT_CON;
 +    content->layout = L_SPLITH;
      FREE(content->name);
      content->name = sstrdup("content");
  
      Con *bottomdock = con_new(NULL, NULL);
      bottomdock->type = CT_DOCKAREA;
      bottomdock->layout = L_DOCKAREA;
 -    bottomdock->orientation = VERT;
      /* this container swallows dock clients */
      match = scalloc(sizeof(Match));
      match_init(match);
@@@ -358,6 -359,19 +358,19 @@@ void init_ws_for_output(Output *output
              workspace_show(previous);
          }
  
+         /* Render the output on which the workspace was to get correct Rects.
+          * Then, we need to work with the "content" container, since we cannot
+          * be sure that the workspace itself was rendered at all (in case it’s
+          * invisible, it won’t be rendered). */
+         render_con(workspace_out, false);
+         Con *ws_out_content = output_get_content(workspace_out);
+         Con *floating_con;
+         TAILQ_FOREACH(floating_con, &(workspace->floating_head), floating_windows)
+             /* NB: We use output->con here because content is not yet rendered,
+              * so it has a rect of {0, 0, 0, 0}. */
+             floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect));
          con_detach(workspace);
          con_attach(workspace, content, false);
  
@@@ -446,11 -460,11 +459,11 @@@ static void output_change_mode(xcb_conn
              if (con_num_children(workspace) > 1)
                  continue;
  
 -            workspace->orientation = (output->rect.height > output->rect.width) ? VERT : HORIZ;
 -            DLOG("Setting workspace [%d,%s]'s orientation to %d.\n", workspace->num, workspace->name, workspace->orientation);
 +            workspace->layout = (output->rect.height > output->rect.width) ? L_SPLITV : L_SPLITH;
 +            DLOG("Setting workspace [%d,%s]'s layout to %d.\n", workspace->num, workspace->name, workspace->layout);
              if ((child = TAILQ_FIRST(&(workspace->nodes_head)))) {
 -                child->orientation = workspace->orientation;
 -                DLOG("Setting child [%d,%s]'s orientation to %d.\n", child->num, child->name, child->orientation);
 +                child->layout = workspace->layout;
 +                DLOG("Setting child [%d,%s]'s layout to %d.\n", child->num, child->name, child->layout);
              }
          }
      }
@@@ -681,7 -695,7 +694,7 @@@ void randr_query_outputs(void) 
                      DLOG("Fixing the coordinates of floating containers\n");
                      Con *floating_con;
                      TAILQ_FOREACH(floating_con, &(current->floating_head), floating_windows)
-                         floating_fix_coordinates(floating_con, &(old_content->rect), &(first_content->rect));
+                         floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect));
                      DLOG("Done, next\n");
                  }
                  DLOG("re-attached all workspaces\n");