Geometry can be set using percent.
Placement can be called
From 0f3e6c70bbe61da481769f705e230f7b7f2c703b Mon Sep 17 00:00:00 2001
From: Cedric GESTES <cta...@gmail.com>
Date: Sat, 12 Sep 2009 22:54:19 +0200
Subject: [PATCH] rules: rework for placement and geometry

Signed-off-by: Cedric GESTES <cta...@gmail.com>
---
 lib/awful/rules.lua.in |  120 ++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 96 insertions(+), 24 deletions(-)

diff --git a/lib/awful/rules.lua.in b/lib/awful/rules.lua.in
index 8b6151f..9eaf5b9 100644
--- a/lib/awful/rules.lua.in
+++ b/lib/awful/rules.lua.in
@@ -11,6 +11,10 @@ local ipairs = ipairs
 local pairs = pairs
 local aclient = require("awful.client")
 local atag = require("awful.tag")
+local aplacement = require("awful.placement")
+local capi = {
+    screen = screen
+}
 
 --- Apply rules to clients at startup.
 module("awful.rules")
@@ -47,6 +51,13 @@ module("awful.rules")
 --   properties = { tag = mytagobject, switchtotag = true } }
 -- </code>
 -- </p>
+-- <p>If you want to put Emacs floating, centered with a width of 60% and a height of 200px:
+-- <br/>
+-- <code>
+-- { rule = { class = "Emacs" }
+--   properties = { width = "60%", floating = true, height = 200 , placement = "centered" } }
+-- </code>
+-- </p>
 -- <p>Note that all "rule" entries need to match. If any of the entry does not
 -- match, the rule won't be applied.</p>
 -- <p>If a client matches multiple rules, their applied in the order they are
@@ -56,6 +67,7 @@ module("awful.rules")
 -- @class table
 -- @name rules
 rules = {}
+properties = {}
 
 --- Check if a client match a rule.
 -- @param c The client.
@@ -78,35 +90,95 @@ function match(c, rule)
     return true
 end
 
+--- Apply a gemetry property on a client
+-- @param c The client
+-- @param property The property name
+-- @param value The value to set
+-- @return true is the property match
+function properties.setgeometry(c, property, value)
+    if  property == "height" or
+        property == "width"  or
+        property == "x"      or
+        property == "y" then
+
+        local geo = c:geometry();
+        repeat
+            if type(value) == "string" then
+                v,percent = value:match("(%d*)(%%*)")
+                if v and percent == "%" then
+                    local screen_geometry = capi.screen[c.screen].workarea
+                    screen_geometry.x = screen_geometry.width
+                    screen_geometry.y = screen_geometry.height
+                    geo[property] = screen_geometry[property] * v / 100
+                    break
+                elseif v then
+                    geo[property] = v
+                    break
+                end
+            else
+                geo[property] = value
+            end
+        until true
+        c:geometry(geo);
+    end
+    return false
+end
+
+--- Apply a placement property on a client
+-- @param c The client
+-- @param property The property name
+-- @param value The value to set
+-- @return true is the property match
+function properties.setplacement(c, property, value)
+    if property == "placement" then
+        if type(aplacement[value]) == "function" then
+            aplacement[value](c)
+        end
+    end
+    return false
+end
+
+--- Apply a set of properties on a client
+-- @param c The client
+-- @param props a dictionary of properties
+function properties.set(c, props)
+    if props == nil then
+        return
+    end
+    for property, value in pairs(props) do
+        repeat
+            if property == "floating" then
+                aclient.floating.set(c, value)
+            elseif property == "tag" then
+                aclient.movetotag(value, c)
+            elseif property == "switchtotag" then
+                if props.tag then atag.viewonly(props.tag) end
+            elseif properties.setgeometry(c, property, value) then
+                break --this is continue
+            elseif properties.setplacement(c, property, value) then
+                break --this is continue
+            elseif type(c[property]) == "function" then
+                c[property](c, value)
+            elseif property ~= "switchtotag" and property ~= "focus" then
+                c[property] = value
+            end
+        until true
+    end
+
+    -- Do this at last so we do not erase things done by the focus
+    -- signal.
+    if props.focus then
+        client.focus = c
+    end
+end
+
+
 --- Apply rules to a client.
 -- @param c The client.
 function apply(c)
     for _, entry in ipairs(rules) do
         if match(c, entry.rule) then
-            for property, value in pairs(entry.properties) do
-                if property == "floating" then
-                    aclient.floating.set(c, value)
-                elseif property == "tag" then
-                    aclient.movetotag(value, c)
-                elseif property == "switchtotag" and value
-                    and entry.properties["tag"] then
-                    atag.viewonly(entry.properties["tag"])
-                elseif property == "height" or property == "width" or
-                       property == "x" or property == "y" then
-                    local geo = c:geometry();
-                    geo[property] = value
-                    c:geometry(geo);
-                elseif type(c[property]) == "function" then
-                    c[property](c, value)
-                else
-                    c[property] = value
-                end
-            end
-            -- Do this at last so we do not erase things done by the focus
-            -- signal.
-            if entry.properties.focus then
-                client.focus = c
-            end
+            properties.set(c, entry.properties)
         end
     end
 end
-- 
1.6.0.4

Reply via email to