Tiling2: Restrict allowed resizes of windows.
authorTom Hacohen <tom@stosb.com>
Thu, 16 Jan 2014 17:18:29 +0000 (17:18 +0000)
committerTom Hacohen <tom@stosb.com>
Fri, 21 Feb 2014 09:15:07 +0000 (09:15 +0000)
src/modules/tiling/e_mod_tiling.c
src/modules/tiling/window_tree.c
src/modules/tiling/window_tree.h

index 6965dad..c014ea8 100644 (file)
@@ -732,6 +732,108 @@ static void _move_or_resize(E_Client *ec)
     _reapply_tree();
 }
 
+static void
+_resize_begin_hook(void *data EINA_UNUSED, E_Client *ec)
+{
+    Client_Extra *extra;
+
+    if (!ec) {
+        return;
+    }
+    if (!is_tilable(ec)) {
+        return;
+    }
+
+    if (!desk_should_tile_check(ec->desk))
+        return;
+
+    extra = eina_hash_find(_G.client_extras, &ec);
+    if (!extra) {
+        ERR("No extra for %p", ec);
+        return;
+    }
+
+    if (is_ignored_window(extra))
+       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 edges = tiling_window_tree_edges_get(item);
+    if (edges & TILING_WINDOW_TREE_EDGE_LEFT)
+      {
+         switch (ec->resize_mode)
+           {
+            case E_POINTER_RESIZE_L:
+               ec->resize_mode = E_POINTER_RESIZE_NONE;
+               break;
+            case E_POINTER_RESIZE_TL:
+               ec->resize_mode = E_POINTER_RESIZE_T;
+               break;
+            case E_POINTER_RESIZE_BL:
+               ec->resize_mode = E_POINTER_RESIZE_B;
+               break;
+            default:
+               break;
+           }
+      }
+    if (edges & TILING_WINDOW_TREE_EDGE_RIGHT)
+      {
+         switch (ec->resize_mode)
+           {
+            case E_POINTER_RESIZE_R:
+               ec->resize_mode = E_POINTER_RESIZE_NONE;
+               break;
+            case E_POINTER_RESIZE_TR:
+               ec->resize_mode = E_POINTER_RESIZE_T;
+               break;
+            case E_POINTER_RESIZE_BR:
+               ec->resize_mode = E_POINTER_RESIZE_B;
+               break;
+            default:
+               break;
+           }
+      }
+    if (edges & TILING_WINDOW_TREE_EDGE_TOP)
+      {
+         switch (ec->resize_mode)
+           {
+            case E_POINTER_RESIZE_T:
+               ec->resize_mode = E_POINTER_RESIZE_NONE;
+               break;
+            case E_POINTER_RESIZE_TL:
+               ec->resize_mode = E_POINTER_RESIZE_L;
+               break;
+            case E_POINTER_RESIZE_TR:
+               ec->resize_mode = E_POINTER_RESIZE_R;
+               break;
+            default:
+               break;
+           }
+      }
+    if (edges & TILING_WINDOW_TREE_EDGE_BOTTOM)
+      {
+         switch (ec->resize_mode)
+           {
+            case E_POINTER_RESIZE_B:
+               ec->resize_mode = E_POINTER_RESIZE_NONE;
+               break;
+            case E_POINTER_RESIZE_BL:
+               ec->resize_mode = E_POINTER_RESIZE_L;
+               break;
+            case E_POINTER_RESIZE_BR:
+               ec->resize_mode = E_POINTER_RESIZE_R;
+               break;
+            default:
+               break;
+           }
+      }
+}
+
 static Eina_Bool
 _resize_hook(void *data __UNUSED__, int type __UNUSED__, E_Event_Client *event)
 {
@@ -1014,6 +1116,7 @@ e_modapi_init(E_Module *m)
                                  (Ecore_Event_Handler_Cb) _f, \
                                  NULL);
 
+    e_client_hook_add(E_CLIENT_HOOK_RESIZE_BEGIN, _resize_begin_hook, NULL);
     HANDLER(_G.handler_client_resize, CLIENT_RESIZE, _resize_hook);
     HANDLER(_G.handler_client_move, CLIENT_MOVE, _move_hook);
     HANDLER(_G.handler_client_add, CLIENT_ADD, _add_hook);
index 0ecc77a..64a71c0 100644 (file)
@@ -396,6 +396,55 @@ tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int
    return ret;
 }
 
+int
+_tiling_window_tree_edges_get_helper(Window_Tree *node, Tiling_Split_Type split_type, Eina_Bool gave_up_this,
+      Eina_Bool gave_up_parent)
+{
+   int ret = TILING_WINDOW_TREE_EDGE_LEFT | TILING_WINDOW_TREE_EDGE_RIGHT |
+      TILING_WINDOW_TREE_EDGE_TOP | TILING_WINDOW_TREE_EDGE_BOTTOM;
+   if (!node->parent)
+     {
+        return ret;
+     }
+   else if (gave_up_this && gave_up_parent)
+     {
+        return 0;
+     }
+   else if (gave_up_this)
+     {
+        /* Mixed the gave_up vals on purpose, we do it on every call. */
+        return _tiling_window_tree_edges_get_helper(node->parent, !split_type ,gave_up_parent,
+              gave_up_this);
+     }
+
+   if (EINA_INLIST_GET(node)->prev)
+     {
+        gave_up_this = EINA_TRUE;
+        ret ^= (split_type == TILING_SPLIT_HORIZONTAL) ?
+           TILING_WINDOW_TREE_EDGE_LEFT : TILING_WINDOW_TREE_EDGE_TOP;
+     }
+
+   if (EINA_INLIST_GET(node)->next)
+     {
+        gave_up_this = EINA_TRUE;
+        ret ^= (split_type == TILING_SPLIT_HORIZONTAL) ?
+           TILING_WINDOW_TREE_EDGE_RIGHT : TILING_WINDOW_TREE_EDGE_BOTTOM;
+     }
+
+   /* Mixed the gave_up vals on purpose, we do it on every call. */
+   return ret & _tiling_window_tree_edges_get_helper(node->parent, !split_type ,gave_up_parent,
+         gave_up_this);
+}
+
+int
+tiling_window_tree_edges_get(Window_Tree *node)
+{
+   Tiling_Split_Type split_type = _tiling_window_tree_split_type_get(node);
+
+   return _tiling_window_tree_edges_get_helper(node, !split_type, EINA_FALSE,
+         EINA_FALSE);
+}
+
 void
 tiling_window_tree_dump(Window_Tree *root, int level)
 {
index 6cca18c..424a929 100644 (file)
@@ -21,6 +21,13 @@ struct _Window_Tree
    double weight;
 };
 
+#define TILING_WINDOW_TREE_EDGE_LEFT (1 << 0)
+#define TILING_WINDOW_TREE_EDGE_RIGHT (1 << 1)
+#define TILING_WINDOW_TREE_EDGE_TOP (1 << 2)
+#define TILING_WINDOW_TREE_EDGE_BOTTOM (1 << 3)
+
+int tiling_window_tree_edges_get(Window_Tree *node);
+
 void tiling_window_tree_free(Window_Tree *root);
 void tiling_window_tree_walk(Window_Tree *root, void (*func)(void *));