Tiling2: Added resizing support.
authorTom Hacohen <tom@stosb.com>
Tue, 14 Jan 2014 17:25:32 +0000 (17:25 +0000)
committerTom Hacohen <tom@stosb.com>
Fri, 21 Feb 2014 09:15:06 +0000 (09:15 +0000)
There are still some bugs.

src/modules/tiling/e_mod_tiling.c
src/modules/tiling/window_tree.c
src/modules/tiling/window_tree.h

index 13cbb0f..b317e26 100644 (file)
@@ -333,10 +333,18 @@ tiling_e_client_move_resize_extra(E_Client *ec,
                       int       w,
                       int       h)
 {
-   Client_Extra *extra = _get_or_create_client_extra(ec);
-   if (!extra) {
+    Client_Extra *extra = eina_hash_find(_G.client_extras, &ec);
+    if (!extra) {
         ERR("No extra for %p", ec);
-   }
+        return;
+    }
+
+    extra->expected = (geom_t) {
+         .x = x,
+         .y = y,
+         .w = w,
+         .h = h,
+    };
 
    _e_client_move_resize(ec, x, y, w, h);
 }
@@ -597,6 +605,12 @@ static void _move_or_resize(E_Client *ec)
     if (!ec) {
         return;
     }
+    if (is_floating_window(ec)) {
+        return;
+    }
+    if (!is_tilable(ec)) {
+        return;
+    }
 
     if (!desk_should_tile_check(ec->desk))
         return;
@@ -618,6 +632,47 @@ static void _move_or_resize(E_Client *ec)
         return;
     }
 
+    if ((ec->x == extra->expected.x) && (ec->y == extra->expected.y) &&
+          (ec->w == extra->expected.w) && (ec->h == extra->expected.h))
+      {
+
+         return;
+      }
+
+    Window_Tree *item = tiling_window_tree_client_find(_G.tinfo->tree, ec);
+    if (!item)
+      {
+         ERR("Couldn't find tree item for resized client %p!", ec);
+         return;
+      }
+
+      {
+         int w_dir = 1, h_dir = 1;
+         double w_diff = 1.0, h_diff = 1.0;
+         if (abs(extra->expected.w - ec->w) >= MAX(ec->icccm.step_w, 1))
+           {
+              w_diff = ((double) ec->w) / extra->expected.w;
+              printf("w %d %d %f\n", extra->expected.w, ec->w, w_diff);
+           }
+         if (abs(extra->expected.h - ec->h) >= MAX(ec->icccm.step_h, 1))
+           {
+              h_diff = ((double) ec->h) / extra->expected.h;
+              printf("h %d %d %f\n", extra->expected.h, ec->h, h_diff);
+           }
+         if (extra->expected.x != ec->x)
+           {
+              w_dir = -1;
+           }
+         if (extra->expected.y != ec->y)
+           {
+              h_dir = -1;
+           }
+         if ((w_diff != 1.0) || (h_diff != 1.0))
+           {
+              tiling_window_tree_node_resize(item, w_dir, w_diff, h_dir, h_diff);
+           }
+      }
+
     _reapply_tree();
 }
 
index 350966e..41ee12e 100644 (file)
@@ -281,6 +281,100 @@ tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y,
    _tiling_window_tree_level_apply(root, x, y, w, h, 0);
 }
 
+static Window_Tree *
+_inlist_next(Window_Tree *it)
+{
+   return (Window_Tree *) EINA_INLIST_GET(it)->next;
+}
+
+static Window_Tree *
+_inlist_prev(Window_Tree *it)
+{
+   return (Window_Tree *) EINA_INLIST_GET(it)->prev;
+}
+
+static void
+_tiling_window_tree_node_resize_direction(Window_Tree *node, Window_Tree *parent,
+      double dir_diff, int dir)
+{
+   double weight = 0.0;
+   double weight_diff;
+   Window_Tree *children_start;
+   Window_Tree *itr;
+   Window_Tree *(*itr_func)(Window_Tree *);
+
+   if (dir > 0)
+     {
+        itr_func = _inlist_prev;
+        children_start = (Window_Tree *) parent->children->last;
+     }
+   else
+     {
+        itr_func = _inlist_next;
+        children_start = (Window_Tree *) parent->children;
+     }
+
+
+   itr = (Window_Tree *) children_start;
+   while (itr != node)
+     {
+        weight += itr->weight;
+
+        itr = itr_func(itr);
+     }
+
+   if (weight == 0.0)
+      return;
+
+   weight_diff = itr->weight;
+   itr->weight *= dir_diff;
+   weight_diff -= itr->weight;
+   weight_diff /= weight;
+
+   for (itr = children_start ; itr != node ; itr = itr_func(itr))
+     {
+        itr->weight += itr->weight * weight_diff;
+     }
+}
+
+void
+tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int h_dir, double h_diff)
+{
+   Window_Tree *parent = node->parent;
+   Window_Tree *w_parent, *h_parent;
+
+   /* If we have no parent, means we need to be full screen anyway. */
+   if (!parent)
+      return;
+
+   Window_Tree *grand_parent = parent->parent;
+   Tiling_Split_Type parent_split_type = _tiling_window_tree_split_type_get(parent);
+
+   /* w_diff related changes. */
+   if (parent_split_type == TILING_SPLIT_HORIZONTAL)
+     {
+        w_parent = parent;
+        h_parent = grand_parent;
+     }
+   else
+     {
+        w_parent = grand_parent;
+        h_parent = parent;
+     }
+
+   if ((h_diff != 1.0) && h_parent)
+     {
+        Window_Tree *tmp_node = (h_parent == parent) ? node : parent;
+        _tiling_window_tree_node_resize_direction(tmp_node, h_parent, h_diff, h_dir);
+     }
+
+   if ((w_diff != 1.0) && w_parent)
+     {
+        Window_Tree *tmp_node = (w_parent == parent) ? node : parent;
+        _tiling_window_tree_node_resize_direction(tmp_node, w_parent, w_diff, w_dir);
+     }
+}
+
 void
 tiling_window_tree_dump(Window_Tree *root, int level)
 {
index 520899c..5241e27 100644 (file)
@@ -18,7 +18,7 @@ struct _Window_Tree
    /* FIXME: client is falid iff children is null. Sholud enforce it. */
    Eina_Inlist *children; /* Window_Tree * type */
    E_Client *client;
-   float weight;
+   double weight;
 };
 
 void tiling_window_tree_free(Window_Tree *root);
@@ -32,4 +32,6 @@ Window_Tree *tiling_window_tree_client_find(Window_Tree *root, E_Client *client)
 
 void tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
 
+void tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int h_dir, double h_diff);
+
 #endif