Comply with the new official client creation sequence

Tyrannical now use awful.rules for more callbacks. It can be
better integrated, but that's enough for this commit.

This commit also drop the legacy and request sub-module, as the
legacy was dead code anyway amd requests are now mandatory.
This commit is contained in:
Emmanuel Lepage Vallee 2016-11-27 05:06:42 -05:00
parent b4df05fa1d
commit a0fa9a4e35
4 changed files with 105 additions and 163 deletions

View File

@ -1,61 +0,0 @@
-- This file is used to store former Tyrannical features now part
-- of upstream. They are kept to support the older versions
local capi = {client = client , tag = tag , awesome = awesome,
screen = screen , mouse = mouse }
local awful = require("awful")
-- Check is Awesome is 3.5.3+
if capi.awesome.startup == nil then
-- Monkey patch a bug fixed in 3.5.3
awful.tag.setscreen = function(tag,screen)
if not tag or type(tag) ~= "tag" then return end
awful.tag._setscreen(tag,screen)
for k,c in ipairs(tag:clients()) do
c.screen = screen or 1 --Move all clients
c:tags({tag}) --Prevent some very strange side effects, does create some issue with multitag clients
end
awful.tag.history.restore(tag.screen,1)
end
else
-- Restore the old behavior in newer Awesome
require("tyrannical.extra.request")
end
awful.tag.swap = function(tag1,tag2)
local idx1,idx2,scr2 = awful.tag.getidx(tag1),awful.tag.getidx(tag2),awful.tag.getscreen(tag2)
awful.tag.setscreen(tag2,awful.tag.getscreen(tag1))
awful.tag.move(idx1,tag2)
awful.tag.setscreen(tag1,scr2)
awful.tag.move(idx2,tag1)
end
-- Check if adding support for sn-based spawn is necessary
if not awful.spawn then
awful.spawn = {snid_buffer={}}
function awful.util.spawn(cmd,sn_rules,callback)
if cmd and cmd ~= "" then
local enable_sn = (sn_rules ~= false or callback) and true or true
if not sn_rules and callback then
sn_rules = {callback=callback}
elseif callback then
sn_rules.callback = callback
end
local pid,snid = capi.awesome.spawn(cmd, enable_sn)
-- The snid will be nil in case of failure
if snid and type(sn_rules) == "table" then
awful.spawn.snid_buffer[snid] = sn_rules
end
return pid,snid
end
-- For consistency
return "Error: No command to execute"
end
local function on_canceled(sn)
awful.spawn.snid_buffer[sn] = nil
end
capi.awesome.connect_signal("spawn::canceled" , on_canceled )
capi.awesome.connect_signal("spawn::timeout" , on_canceled )
else
-- Then if it's there, disable the part we don't want
capi.client.disconnect_signal("manage",awful.spawn.on_snid_callback)
end

View File

@ -1,40 +0,0 @@
local capi = {client=client,awesome=awesome}
local ewmh = require("awful.ewmh")
local tyrannical = nil
-- Use Tyrannical policies instead of the default ones
capi.client.disconnect_signal("request::activate",ewmh.activate)
capi.client.connect_signal("request::activate",function(c,reason)
if not tyrannical then
tyrannical = require("tyrannical")
end
-- Always grant those request as it probably mean that it is a modal dialog
if c.transient_for and capi.client.focus == c.transient_for then
capi.client.focus = c
c:raise()
-- If it is not modal, then use the normal code path
elseif reason == "rule" or reason == "ewmh" then
tyrannical.focus_client(c)
-- Tyrannical doesn't have enough information, grant the request
else
capi.client.focus = c
c:raise()
end
end)
capi.client.disconnect_signal("request::tag", ewmh.tag)
capi.client.connect_signal("request::tag", function(c)
-- if capi.awesome.startup then
-- --TODO create a tag on that screen
-- else
-- --TODO block invalid requests, let Tyrannical do its job
-- local tags = c:tags()
-- if #tags == 0 then
-- --TODO cannot happen
-- end
-- end
end)
--lib/awful/tag.lua.in:capi.tag.connect_signal("request::select", tag.viewonly)

153
init.lua
View File

@ -1,9 +1,8 @@
local setmetatable = setmetatable local setmetatable = setmetatable
local print , pairs = print , pairs local print , pairs = print , pairs
local ipairs , type = ipairs , type local ipairs , type = ipairs , type
local string , unpack= string , unpack local string , unpack= string , unpack or table.unpack
local awful = require("awful") local awful = require("awful")
require("tyrannical.extra.legacy")
local capi,sn_callback = {client = client, tag = tag, awesome = awesome, local capi,sn_callback = {client = client, tag = tag, awesome = awesome,
screen = screen, mouse = mouse},awful.spawn and awful.spawn.snid_buffer or {} screen = screen, mouse = mouse},awful.spawn and awful.spawn.snid_buffer or {}
@ -81,13 +80,15 @@ local function load_property(name,property)
end end
end end
--Check all focus policies then change focus (Awesome 3.5.3+)
function module.focus_client(c,properties) function module.focus_client(c,properties)
local properties = properties or (c_rules.instance[string.lower(c.instance or "N/A")] or {}).properties or (c_rules.class[string.lower(get_class(c))] or {}).properties or {}
if (((not c.transient_for) or (c.transient_for==capi.client.focus) or (not settings.block_children_focus_stealing)) and (not properties.no_autofocus)) then if (((not c.transient_for) or (c.transient_for==capi.client.focus) or (not settings.block_children_focus_stealing)) and (not c.no_autofocus)) then
if not awful.util.table.hasitem(c:tags(), (c.screen or capi.screen[1]).selected_tag) and (not prop(c:tags()[1],"no_focus_stealing_in")) then local tags = c:tags()
if #tags > 0 and not c:isvisible() and not tags[1].no_focus_stealing_in then
c:tags()[1]:view_only() c:tags()[1]:view_only()
end end
capi.client.focus = c capi.client.focus = c
c:raise() c:raise()
return true return true
@ -95,34 +96,32 @@ function module.focus_client(c,properties)
end end
--Apply all properties --Apply all properties
local function apply_properties(c,override,normal) local function apply_properties(c, props, callbacks)
if not override and not normal then return nil,{} end
local props,ret = awful.util.table.join(settings.client,normal or {},override, local force_intrusive = settings.force_odd_as_intrusive
override.callback and override.callback(c) or (normal and normal.callback and normal.callback(c)) or {}),nil and c.type ~= "normal"
--Set all 'c.something' properties, --TODO maybe eventually move to awful.rules.execute
for k,_ in pairs(props) do local is_intrusive = force_intrusive
c[k] = props[k] or type(props.intrusive) == "function" and props.intrusive(c)
or props.intrusive
--Check if the client should be added to an existing tag (or tags)
if (not props.new_tag) and is_intrusive then
local tag = c.screen.selected_tag
or c.screen.tags[1]:view_only()
or c.screen.selected_tag
if tag then --Can be false if there is no tags
props.tag, props.tags = tag, nil
end end
--Center client
if props.centered == true then
awful.placement.centered(c, nil)
end end
awful.rules.execute(c, props, callbacks)
--Set slave or master --Set slave or master
if props.slave == true or props.master == true then if props.slave == true or props.master == true then
awful.client["set"..(props.slave and "slave" or "master")](c, true) awful.client["set"..(props.slave and "slave" or "master")](c, true)
end end
--Check if the client should be added to an existing tag (or tags)
if props.new_tag then
ret = c:tags({awful.tag.add(type(props.new_tag)=="table" and props.new_tag.name or c.class,type(props.new_tag)=="table" and props.new_tag or {screen=c.screen or 1})})
elseif props.tag then
ret = c:tags(type(props.tag) == "function" and props.tag(c) or (type(props.tag) == "table" and props.tag or { props.tag }))
elseif props.intrusive == true or (settings.force_odd_as_intrusive and c.type ~= "normal") then
local tag = c.screen.selected_tag or c.screen.tags[1]:view_only() or c.screen.selected_tag
if tag then --Can be false if there is no tags
ret = c:tags({tag})
end
end
return ret,props
end end
local function select_screen(tag) local function select_screen(tag)
@ -152,16 +151,17 @@ local function select_screen(tag)
end end
--Match client --Match client
local function match_client(c, startup) local function match_client(c, forced_tags, hints)
if not c then return end if (not c) or #c:tags() > 0 then return end
local startup = startup == nil and capi.awesome.startup or startup
local props = c.startup_id and sn_callback[tostring(c.startup_id)] or {} local props = c.startup_id and sn_callback[tostring(c.startup_id)] or {}
local low_i = string.lower(c.instance or "N/A") local low_i = string.lower(c.instance or "N/A")
local low_c = string.lower(get_class(c)) local low_c = string.lower(get_class(c))
local tags = props.tags or {props.tag} local tags = props.tags or {props.tag}
local rules = c_rules.instance[low_i] or c_rules.class[low_c] local rules = c_rules.instance[low_i] or c_rules.class[low_c]
local forced_tags,props = apply_properties(c,props,rules and rules.properties)
if #tags == 0 and c.transient_for and (capi.mouse.screen or (rules and rules.properties.intrusive_popup)) then if #tags == 0 and c.transient_for and (capi.mouse.screen or (rules and rules.properties.intrusive_popup)) then
c.sticky = c.transient_for.sticky or false c.sticky = c.transient_for.sticky or false
c:tags(awful.util.table.join(c.transient_for:tags(),(rules and rules.properties.intrusive_popup) and c.screen.selected_tags)) c:tags(awful.util.table.join(c.transient_for:tags(),(rules and rules.properties.intrusive_popup) and c.screen.selected_tags))
@ -222,6 +222,7 @@ local function match_client(c, startup)
return module.focus_client(c,props) return module.focus_client(c,props)
end end
capi.client.disconnect_signal("request::tag", awful.ewmh.tag)
capi.client.connect_signal("request::tag", match_client) capi.client.connect_signal("request::tag", match_client)
capi.client.connect_signal("untagged", function (c, t) capi.client.connect_signal("untagged", function (c, t)
@ -235,23 +236,7 @@ capi.client.connect_signal("untagged", function (c, t)
end end
end) end)
awful.tag.withcurrent,awful.tag._add = function(c, startup) awful.tag._add = awful.tag.add
local tags,old_tags = {},c:tags()
--Safety to prevent
for k, t in ipairs(old_tags) do
tags[#tags+1] = (t.screen == c.screen) and t or nil
end
--Necessary when dragging clients
if startup == nil and old_tags[1] and old_tags[1].screen ~= c.screen then --nil != false
local sellist = c.screen.selected_tags
if #sellist > 0 then --Use already selected tag
tags = sellist
else --Select a tag
match_client(c, startup)
end
end
c:tags(tags)
end,awful.tag.add
awful.tag.add = function(tag,props,override) awful.tag.add = function(tag,props,override)
props.screen,props.instances = props.screen or capi.mouse.screen,props.instances or setmetatable({}, { __mode = 'v' }) props.screen,props.instances = props.screen or capi.mouse.screen,props.instances or setmetatable({}, { __mode = 'v' })
@ -265,11 +250,9 @@ awful.tag.add = function(tag,props,override)
end end
capi.tag.connect_signal("property::fallback",function(t) capi.tag.connect_signal("property::fallback",function(t)
fallbacks[awful.util.table.hasitem(fallbacks, t) or (#fallbacks+1)] = prop(t,"fallback") and t or nil fallbacks[awful.util.table.hasitem(fallbacks, t) or (#fallbacks+1)] = t.fallback and t or nil
end) end)
local is_init = setmetatable({}, { __mode = 'k' })
local function contain_screen(tab, s) local function contain_screen(tab, s)
for _, v in ipairs(tab) do for _, v in ipairs(tab) do
if type(v) ~= "number" or v <= capi.screen.count() then if type(v) ~= "number" or v <= capi.screen.count() then
@ -284,9 +267,7 @@ local function contain_screen(tab, s)
end end
-- Add init tags to newly connected screens -- Add init tags to newly connected screens
awful.screen.connect_for_each_screen(function(s) --TODO remove the load code and use this awful.screen.connect_for_each_screen(function(s)
if is_init[s] then return end
for _, def in pairs(tags_hash) do for _, def in pairs(tags_hash) do
if def.init then if def.init then
if def.screen and (type(def.screen) == "table" and contain_screen(def.screen, s)) if def.screen and (type(def.screen) == "table" and contain_screen(def.screen, s))
@ -345,6 +326,68 @@ capi.tag.connect_signal("request::screen", function(t)
end end
end) end)
capi.client.disconnect_signal("manage", awful.rules.apply)
capi.client.disconnect_signal("spawn::completed_with_payload", awful.rules.completed_with_payload_callback)
capi.client.disconnect_signal("manage",awful.spawn.on_snid_callback)
--- Replace the default handler to take into account Tyrannical properties
function awful.rules.apply(c)
local low_i = string.lower(c.instance or "N/A")
local low_c = string.lower(get_class(c))
local callbacks, props = {}, {}
local props_src = (c_rules.instance[low_i]
or c_rules.class[low_c] or {}).properties
or {}
-- Add Tyrannical properties
awful.util.table.crush(props,props_src)
-- Add the rules properties
for _, entry in ipairs(awful.rules.matching_rules(c, awful.rules.rules)) do
awful.util.table.crush(props,entry.properties or {})
if entry.callback then
table.insert(callbacks, entry.callback)
end
end
-- Add startup_id overridden properties
if c.startup_id and awful.spawn.snid_buffer[c.startup_id] then
local snprops, sncb = unpack(awful.spawn.snid_buffer[c.startup_id])
-- The SNID tag(s) always have precedence over the rules one(s)
if snprops.tag or snprops.tags or snprops.new_tag then
props.tag, props.tags, props.new_tag, props.intrusive = nil, nil, nil, nil
end
awful.util.table.crush(props,snprops)
awful.util.table.merge(callbacks, sncb)
end
apply_properties(c,props, callbacks)
end
capi.client.connect_signal("manage", awful.rules.apply)
capi.client.disconnect_signal("request::activate",awful.ewmh.activate)
capi.client.connect_signal("request::activate",function(c,reason)
-- Always grant those request as it probably mean that it is a modal dialog
if c.transient_for and capi.client.focus == c.transient_for then
capi.client.focus = c
c:raise()
-- If it is not modal, then use the normal code path
elseif reason == "rule" or reason == "rules" or reason == "ewmh" then
module.focus_client(c)
-- Tyrannical doesn't have enough information, grant the request
else
capi.client.focus = c
c:raise()
end
end)
--------------------------OBJECT GEARS--------------------------- --------------------------OBJECT GEARS---------------------------
local getter = {properties = setmetatable({}, {__newindex = function(table,k,v) load_property(k,v) end}), local getter = {properties = setmetatable({}, {__newindex = function(table,k,v) load_property(k,v) end}),
settings = settings, tags_by_name = tags_hash, sn_callback = sn_callback} settings = settings, tags_by_name = tags_hash, sn_callback = sn_callback}

View File

@ -13,7 +13,7 @@ local glib = require( "lgi" ).GLib
local function get_current_screen() local function get_current_screen()
if capi.client.focus and capi.client.focus.screen == capi.mouse.screen then if capi.client.focus and capi.client.focus.screen == capi.mouse.screen then
return capi.mouse.screen return capi.mouse.screen
elseif (not aw_tag.selected(capi.mouse.screen)) or (#aw_tag.selected(capi.mouse.screen):clients() == 0) or (not capi.client.focus) then elseif (capi.mouse.screen.selected_tag and #capi.mouse.screen.selected_tag:clients() == 0) or (not capi.client.focus) then
return capi.mouse.screen return capi.mouse.screen
end end
return capi.client.focus.screen return capi.client.focus.screen
@ -70,11 +70,11 @@ local function rename_tag()
end end
local function term_in_current_tag() local function term_in_current_tag()
aw_spawn(terminal,{intrusive=true,slave=true}) aw_spawn(terminal,{intrusive=true,slave=true,screen=get_current_screen()})
end end
local function new_tag_with_term() local function new_tag_with_term()
aw_spawn(terminal,{new_tag={volatile = true}}) aw_spawn(terminal,{new_tag={volatile = true,screen=get_current_screen()}})
end end
local function fork_tag() local function fork_tag()
@ -84,7 +84,7 @@ local function fork_tag()
local clients = t:clients() local clients = t:clients()
local t2 = aw_tag.add(t.name,aw_tag.getdata(t)) local t2 = aw_tag.add(t.name,aw_tag.getdata(t))
t2:clients(clients) t2:clients(clients)
aw_tag.viewonly(t2) t2:view_only()
end end
local function aero_tag() local function aero_tag()